#!/usr/bin/env bash

# run-cli.sh
#
# Purpose:
#   Small wrapper to execute the local goat-flow CLI with common command shortcuts.
#
# Usage:
#   bash scripts/run-cli.sh <command> [path] [flags]
#
# Behavior:
#   - builds CLI assets when stale or missing
#   - renders command output with bounded previews for terminal readability
#   - supports audit/setup/test-all workflows defined by the CLI
#
# Exit:
#   0 when requested command succeeds, non-zero on CLI command failure.
#
# Requirements:
#   - node, npm
#   - built CLI available or build tooling installed

set -euo pipefail

ROOT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
cd "$ROOT_DIR"

# Auto-build if src/ is newer than dist/
if [[ ! -f dist/cli/cli.js ]] || [[ -n "$(find src/cli -name '*.ts' -newer dist/cli/cli.js 2>/dev/null | head -1)" ]]; then
    npx tsc 2>&1 || { echo "Build failed" >&2; exit 1; }
fi

cli() { node dist/cli/cli.js "$@"; }

usage() {
    cat <<'EOF'

  Usage: scripts/run-cli.sh <command> [path] [flags]

  Commands:
    audit [path] [flags]    Validate setup correctness (default: .)
    setup [path] [flags]    Generate setup prompt (adapts to project state)
    test-all                Run all human testing gate checks
    test-all --full         Run all checks, show full output

  Examples:
    scripts/run-cli.sh audit .
    scripts/run-cli.sh audit . --agent claude
    scripts/run-cli.sh setup . --agent claude
    scripts/run-cli.sh test-all

EOF
}

# Build if needed
if [[ ! -f dist/cli/cli.js ]]; then
    echo "Building..."
    npm run build
fi

# Show output with smart truncation and header
show() {
    local label="$1" max_lines="$2"
    shift 2
    local output exit_code=0

    output=$("$@" 2>&1) || exit_code=$?

    echo ""
    printf "  \033[1;36m%s\033[0m\n" "$label"
    printf "  \033[2m%s\033[0m\n" "$(printf '%.0s─' {1..40})"

    if [[ -z "$output" ]]; then
        printf "  \033[2m(no output, exit %d)\033[0m\n" "$exit_code"
        return
    fi

    indent_lines() {
        local indent="$1"
        local lines="$2"
        while IFS= read -r line; do
            printf '%s%s\n' "$indent" "$line"
        done <<< "$lines"
    }

    local total_lines
    total_lines=$(wc -l <<< "$output")

    if [[ "$total_lines" -le "$max_lines" ]]; then
        indent_lines "  " "$output"
    else
        indent_lines "  " "$(head -"$max_lines" <<< "$output")"
        printf "  \033[2m... +%d lines (pipe to less or use --format json > file.json)\033[0m\n" $((total_lines - max_lines))
    fi
}

# Check function for test-all
check() {
    local num="$1" name="$2" preview_lines="${3:-5}"
    shift 3
    local output exit_code=0

    output=$("$@" 2>&1) || exit_code=$?

    # Fail if: no output, non-zero exit, or output starts with error markers
    local is_error=0
    [[ -z "$output" ]] && is_error=1
    [[ "$exit_code" -ne 0 ]] && is_error=1
    echo "$output" | head -1 | grep -qiE '^(fatal error|error:|unknown)' && is_error=1

    if [[ "$is_error" -eq 0 ]]; then
        printf "  \033[32m✓\033[0m %s. %s\n" "$num" "$name"
        if [[ "$preview_lines" -gt 0 ]]; then
            head -"$preview_lines" <<< "$output" | sed 's/^/    /'
            local total_lines
            total_lines=$(wc -l <<< "$output")
            if [[ "$total_lines" -gt "$preview_lines" ]]; then
                printf "    \033[2m... (%d more lines)\033[0m\n" $((total_lines - preview_lines))
            fi
        fi
        passed=$((passed + 1))
    else
        printf "  \033[31m✗\033[0m %s. %s (exit %d)\n" "$num" "$name" "$exit_code"
        if [[ -n "$output" ]]; then
            head -3 <<< "$output" | sed 's/^/    /'
        fi
        failed=$((failed + 1))
    fi
}

cmd="${1:-}"

if [[ -z "$cmd" ]]; then
    echo ""
    printf "  \033[1m🐐  GOAT Flow CLI\033[0m\n"
    echo ""
    printf "  \033[2mAudit\033[0m\n"
    printf "  \033[36m1\033[0m  audit .                         Audit current directory\n"
    printf "  \033[36m2\033[0m  audit . --harness               Advisory quality grades\n"
    printf "  \033[36m3\033[0m  audit . --agent claude           Audit one agent only\n"
    echo ""
    printf "  \033[2mGenerate\033[0m\n"
    printf "  \033[36m4\033[0m  setup .                          Setup prompt (adapts to project state)\n"
    echo ""
    printf "  \033[2mTest\033[0m\n"
    printf "  \033[36m5\033[0m  test-all                        Run all human testing gates\n"
    printf "  \033[36mh\033[0m  help                            Show full usage + examples\n"
    echo ""
    printf "  \033[1mPick:\033[0m "
    read -r choice
    case "$choice" in
        1) cli audit . ;;
        2) cli audit . --harness ;;
        3) cli audit . --agent claude ;;
        4)
            echo ""
            printf "  Which agent to set up?\n"
            printf "    \033[36m1\033[0m  Claude Code\n"
            printf "    \033[36m2\033[0m  Codex\n"
            printf "    \033[36m3\033[0m  Antigravity\n"
            printf "  \033[1mPick:\033[0m "
            read -r agent_choice
            case "$agent_choice" in
                1) cli setup . --agent claude ;;
                2) cli setup . --agent codex ;;
                3) cli setup . --agent antigravity ;;
                *) echo "Invalid choice"; exit 1 ;;
            esac
            ;;
        5) cmd="test-all" ;;
        h|H) usage; exit 0 ;;
        *) echo "Invalid choice"; exit 1 ;;
    esac
    [[ "${cmd:-}" != "test-all" ]] && exit 0
fi

shift

case "$cmd" in
    setup)
        # Show agent picker if --agent not already specified
        if echo "$*" | grep -q -- '--agent'; then
            cli setup "$@"
        else
            echo ""
            printf "  Which agent to set up?\n"
            printf "    \033[36m1\033[0m  Claude Code\n"
            printf "    \033[36m2\033[0m  Codex\n"
            printf "    \033[36m3\033[0m  Antigravity\n"
            printf "  \033[1mPick:\033[0m "
            read -r agent_choice
            case "$agent_choice" in
                1) cli setup "$@" --agent claude ;;
                2) cli setup "$@" --agent codex ;;
                3) cli setup "$@" --agent antigravity ;;
                *) echo "Invalid choice"; exit 1 ;;
            esac
        fi
        ;;
    audit)
        cli "$cmd" "$@"
        ;;
    test-all)
        full_mode=0
        [[ "${1:-}" == "--full" ]] && full_mode=1

        if [[ "$full_mode" -eq 1 ]]; then
            # Full output mode - no truncation
            echo ""
            printf "\033[1m  GOAT Flow CLI - Full Output\033[0m\n"

            show "1. JSON output" 9999 cli audit . --format json --agent claude
            show "2. Quality audit" 9999 cli audit . --harness --agent claude
            show "3. Setup prompt" 9999 cli setup . --agent claude
            echo ""
        else
            passed=0
            failed=0
            total=6

            echo ""
            printf "\033[1m  GOAT Flow CLI - Human Testing Gate\033[0m\n"
            echo ""

            printf "\033[1m  Audit\033[0m\n"

            check 1 "JSON output valid" 3 \
                cli audit . --format json

            check 2 "Quality audit renders" 8 \
                cli audit . --harness

            tmp=$(mktemp -d)
            echo '{"name":"empty"}' > "$tmp/package.json"
            check 3 "No-setup project handled" 3 \
                cli audit "$tmp" --format text
            rm -r "$tmp"

            check 4 "Agent filter (claude only)" 4 \
                cli audit . --agent claude --format text

            echo ""
            printf "\033[1m  Prompts\033[0m\n"

            check 5 "Setup prompt generates" 6 \
                cli setup . --agent claude

            tmp=$(mktemp -d)
            echo '{"name":"fresh","scripts":{"start":"node ."}}' > "$tmp/package.json"
            check 6 "Setup prompt (fresh project)" 6 \
                cli setup "$tmp" --agent claude
            rm -r "$tmp"

            echo ""
            printf "  ─────────────────────────────────\n"
            if [[ "$failed" -eq 0 ]]; then
                printf "  \033[32m✓ %d/%d passed\033[0m" "$passed" "$total"
            else
                printf "  \033[31m✗ %d/%d passed, %d failed\033[0m" "$passed" "$total" "$failed"
            fi
            echo ""
            echo ""
        fi
        ;;
    -h|--help|help)
        usage
        ;;
    *)
        echo "Unknown command: $cmd"
        usage
        exit 1
        ;;
esac
