#!/usr/bin/env bash

set -Eeuo pipefail

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
LOCK_FILE="${1:-${PROJECT_ROOT}/skills-lock.json}"
OUTPUT_FILE="${2:-${SCRIPT_DIR}/install-global-skills.sh}"

die() {
    printf 'Error: %s\n' "$1" >&2
    exit 1
}

for command_name in awk chmod mkdir mktemp mv rm sort; do
    if ! command -v "${command_name}" >/dev/null 2>&1; then
        die "Required command not found: ${command_name}"
    fi
done

[[ -f "${LOCK_FILE}" ]] || die "Skills lockfile not found: ${LOCK_FILE}"

mapfile -t records < <(
    awk '
        /^    "[^"]+": \{$/ {
            skill = $1
            gsub(/[":]/, "", skill)
            next
        }

        $1 == "\"source\":" {
            source = $2
            gsub(/[",]/, "", source)
            print source "\t" skill
            skill = ""
        }
    ' "${LOCK_FILE}" | LC_ALL=C sort -t $'\t' -k1,1 -k2,2
)

(( ${#records[@]} > 0 )) || die "No skills found in lockfile: ${LOCK_FILE}"

temporary_file="$(mktemp "${OUTPUT_FILE}.tmp.XXXXXX")"
cleanup() {
    rm -f -- "${temporary_file}"
}
trap cleanup EXIT

{
    printf '%s\n' '#!/usr/bin/env bash'
    printf '\n'
    printf '%s\n' '# This file is generated by scripts/generate-global-skills-installer.sh.'
    printf '%s\n' '# Do not edit manually; regenerate it after changing skills-lock.json.'
    printf '%s\n' '# shellcheck shell=bash'
    printf '\n'
    printf '%s\n' 'set -Eeuo pipefail'
    printf '\n'
    printf 'SKILL_COUNT=%q\n' "${#records[@]}"
    printf 'DRY_RUN=0\n'
    printf 'COPY_MODE=0\n'
    printf 'SHARED_SKILLS_DIR="${SKILLS_GLOBAL_DIR:-${HOME:?HOME must be set}/.agents/skills}"\n'
    printf 'CODEX_HOME_DIR="${CODEX_HOME:-${HOME:?HOME must be set}/.codex}"\n'
    printf 'CODEX_SKILLS_DIR="${CODEX_HOME_DIR}/skills"\n'
    printf '\n'
    printf '%s\n' 'usage() {'
    printf '%s\n' '    cat <<'"'"'USAGE'"'"''
    printf '%s\n' 'Usage: scripts/install-global-skills.sh [options]'
    printf '\n'
    printf '%s\n' 'Install the repository skill baseline globally and bridge it into Codex.'
    printf '\n'
    printf '%s\n' 'Options:'
    printf '%s\n' '  --dry-run  Show commands and filesystem changes without applying them.'
    printf '%s\n' '  --copy     Copy skills into Codex instead of creating symlinks.'
    printf '%s\n' '  --help     Show this help text.'
    printf '\n'
    printf '%s\n' 'Environment:'
    printf '%s\n' '  SKILLS_GLOBAL_DIR  Shared global skills directory (default: ~/.agents/skills).'
    printf '%s\n' '  CODEX_HOME         Codex home directory (default: ~/.codex).'
    printf '%s\n' 'USAGE'
    printf '%s\n' '}'
    printf '\n'
    printf '%s\n' 'die() {'
    printf '%s\n' '    printf '"'"'Error: %s\n'"'"' "$1" >&2'
    printf '%s\n' '    exit 1'
    printf '%s\n' '}'
    printf '\n'
    printf '%s\n' 'print_command() {'
    printf '%s\n' '    printf '"'"'+'"'"''
    printf '%s\n' '    printf '"'"' %q'"'"' "$@"'
    printf '%s\n' '    printf '"'"'\n'"'"''
    printf '%s\n' '}'
    printf '\n'
    printf '%s\n' 'run_command() {'
    printf '%s\n' '    if (( DRY_RUN )); then'
    printf '%s\n' '        print_command "$@"'
    printf '%s\n' '        return 0'
    printf '%s\n' '    fi'
    printf '%s\n' '    "$@"'
    printf '%s\n' '}'
    printf '\n'
    printf '%s\n' 'require_command() {'
    printf '%s\n' '    command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1"'
    printf '%s\n' '}'
    printf '\n'
    printf '%s\n' 'while (( $# > 0 )); do'
    printf '%s\n' '    case "$1" in'
    printf '%s\n' '        --dry-run)'
    printf '%s\n' '            DRY_RUN=1'
    printf '%s\n' '            ;;'
    printf '%s\n' '        --copy)'
    printf '%s\n' '            COPY_MODE=1'
    printf '%s\n' '            ;;'
    printf '%s\n' '        --help|-h)'
    printf '%s\n' '            usage'
    printf '%s\n' '            exit 0'
    printf '%s\n' '            ;;'
    printf '%s\n' '        *)'
    printf '%s\n' '            die "Unknown option: $1 (use --help for usage)"'
    printf '%s\n' '            ;;'
    printf '%s\n' '    esac'
    printf '%s\n' '    shift'
    printf '%s\n' 'done'
    printf '\n'
    printf '%s\n' 'require_command bash'
    printf '%s\n' 'require_command npx'
    printf '%s\n' 'require_command mkdir'
    printf '%s\n' 'require_command ln'
    printf '%s\n' 'require_command readlink'
    printf '%s\n' 'if (( COPY_MODE )); then'
    printf '%s\n' '    require_command cp'
    printf '%s\n' '    require_command diff'
    printf '%s\n' 'fi'
    printf '\n'
    printf '%s\n' 'printf '"'"'Installing %d skills globally...\n'"'"' "$SKILL_COUNT"'
    printf '\n'

    current_source=""
    source_skill_args=()
    for record in "${records[@]}"; do
        source="${record%%$'\t'*}"
        skill="${record#*$'\t'}"

        if [[ -n "${current_source}" && "${source}" != "${current_source}" ]]; then
            printf 'run_command npx --yes skills add %q --global --yes' "${current_source}"
            for skill_arg in "${source_skill_args[@]}"; do
                printf ' --skill %q' "${skill_arg}"
            done
            printf '\n\n'
            source_skill_args=()
        fi

        current_source="${source}"
        source_skill_args+=("${skill}")
    done

    printf 'run_command npx --yes skills add %q --global --yes' "${current_source}"
    for skill_arg in "${source_skill_args[@]}"; do
        printf ' --skill %q' "${skill_arg}"
    done
    printf '\n\n'

    printf '%s\n' 'SKILLS=('
    for record in "${records[@]}"; do
        skill="${record#*$'\t'}"
        printf '    %q\n' "${skill}"
    done
    printf '%s\n' ')'
    printf '\n'
    printf '%s\n' 'if (( DRY_RUN )); then'
    printf '%s\n' '    printf '"'"'Would bridge skills from %s to %s\n'"'"' "$SHARED_SKILLS_DIR" "$CODEX_SKILLS_DIR"'
    printf '%s\n' '    for skill in "${SKILLS[@]}"; do'
    printf '%s\n' '        if (( COPY_MODE )); then'
    printf '%s\n' '            printf '"'"'+ copy %s -> %s/%s\n'"'"' "$SHARED_SKILLS_DIR/$skill" "$CODEX_SKILLS_DIR" "$skill"'
    printf '%s\n' '        else'
    printf '%s\n' '            printf '"'"'+ ln -s %s %s/%s\n'"'"' "$SHARED_SKILLS_DIR/$skill" "$CODEX_SKILLS_DIR" "$skill"'
    printf '%s\n' '        fi'
    printf '%s\n' '    done'
    printf '%s\n' '    exit 0'
    printf '%s\n' 'fi'
    printf '\n'
    printf '%s\n' 'run_command mkdir -p "$CODEX_SKILLS_DIR"'
    printf '%s\n' 'conflict_count=0'
    printf '%s\n' 'for skill in "${SKILLS[@]}"; do'
    printf '%s\n' '    source_path="$SHARED_SKILLS_DIR/$skill"'
    printf '%s\n' '    target_path="$CODEX_SKILLS_DIR/$skill"'
    printf '%s\n' '    [[ -d "$source_path" ]] || { printf '"'"'Error: Installed skill is missing: %s\n'"'"' "$source_path" >&2; conflict_count=$((conflict_count + 1)); continue; }'
    printf '%s\n' '    if [[ -L "$target_path" ]]; then'
    printf '%s\n' '        if [[ "$(readlink "$target_path")" == "$source_path" ]]; then'
    printf '%s\n' '            printf '"'"'Already linked: %s\n'"'"' "$skill"'
    printf '%s\n' '            continue'
    printf '%s\n' '        fi'
    printf '%s\n' '        printf '"'"'Error: Refusing to replace unmanaged symlink: %s\n'"'"' "$target_path" >&2'
    printf '%s\n' '        conflict_count=$((conflict_count + 1))'
    printf '%s\n' '        continue'
    printf '%s\n' '    fi'
    printf '%s\n' '    if [[ -e "$target_path" ]]; then'
    printf '%s\n' '        if (( COPY_MODE )) && [[ -d "$target_path" ]] && diff -qr -- "$source_path" "$target_path" >/dev/null; then'
    printf '%s\n' '            printf '"'"'Already copied: %s\n'"'"' "$skill"'
    printf '%s\n' '            continue'
    printf '%s\n' '        fi'
    printf '%s\n' '        printf '"'"'Error: Refusing to overwrite existing path: %s\n'"'"' "$target_path" >&2'
    printf '%s\n' '        conflict_count=$((conflict_count + 1))'
    printf '%s\n' '        continue'
    printf '%s\n' '    fi'
    printf '%s\n' '    if (( COPY_MODE )); then'
    printf '%s\n' '        run_command cp -R -- "$source_path" "$target_path"'
    printf '%s\n' '        printf '"'"'Copied: %s\n'"'"' "$skill"'
    printf '%s\n' '    else'
    printf '%s\n' '        run_command ln -s -- "$source_path" "$target_path"'
    printf '%s\n' '        printf '"'"'Linked: %s\n'"'"' "$skill"'
    printf '%s\n' '    fi'
    printf '%s\n' 'done'
    printf '\n'
    printf '%s\n' '(( conflict_count == 0 )) || die "${conflict_count} skill bridge conflict(s) require manual resolution"'
    printf '%s\n' 'printf '"'"'Global skills installation complete.\n'"'"''
} >"${temporary_file}"

chmod 755 "${temporary_file}"
mkdir -p -- "$(dirname -- "${OUTPUT_FILE}")"
mv -- "${temporary_file}" "${OUTPUT_FILE}"
trap - EXIT

printf 'Generated %s from %s (%d skills).\n' "${OUTPUT_FILE}" "${LOCK_FILE}" "${#records[@]}"
