#!/usr/bin/env bash
###############################################################################
# run.sh — Proxym End-to-End Example: TypeScript TODO App
#
# Demonstrates the full proxym workflow using only CLI commands:
#   1. Creates a TypeScript project scaffold on disk
#   2. Registers it in proxym (proxym project add)
#   3. Creates a sprint with tickets (proxym sprint create, proxym ticket add)
#   4. Dispatches tickets to AI tools (proxym tools dispatch)
#   5. Analyzes results (proxym analyze)
#   6. Verifies the build (npm install, build, test)
#
# Usage:
#   bash examples/todo-app-ts/run.sh                     # full run
#   bash examples/todo-app-ts/run.sh --dry-run           # plan only
#   bash examples/todo-app-ts/run.sh --skip-dispatch     # setup only
#   bash examples/todo-app-ts/run.sh --project-dir /tmp/my-todo
#
# Prerequisites:
#   - proxym server running (proxym serve)
#   - Node.js >= 18 installed
###############################################################################
set -euo pipefail

# ── Configuration ────────────────────────────────────────────────────────────

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROXYM_URL="${PROXYM_URL:-${DEFAULT_PROXY_URL:-http://localhost:4000}}"
PROJECT_DIR="${PROJECT_DIR:-$HOME/projects/todo-app-ts}"
TOOL="${TOOL:-aider}"
DRY_RUN=false
SKIP_DISPATCH=false
CLEAN=false
TEMPLATES_DIR="${SCRIPT_DIR}/templates"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --dry-run)       DRY_RUN=true; shift ;;
    --skip-dispatch) SKIP_DISPATCH=true; shift ;;
    --clean)         CLEAN=true; shift ;;
    --project-dir)   PROJECT_DIR="$2"; shift 2 ;;
    --tool)          TOOL="$2"; shift 2 ;;
    --proxy)         PROXYM_URL="$2"; shift 2 ;;
    --help|-h)
      sed -n '2,/^###/p' "$0" | head -n -1 | sed 's/^# \?//'
      exit 0
      ;;
    *) echo "Unknown option: $1"; exit 1 ;;
  esac
done

CLI="proxym --proxy $PROXYM_URL"

# ── Color helpers ────────────────────────────────────────────────────────────

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; RESET='\033[0m'

_hdr()  { echo -e "\n${BOLD}${CYAN}═══ $1 ═══${RESET}"; }
_ok()   { echo -e "  ${GREEN}✓${RESET} $1"; }
_warn() { echo -e "  ${YELLOW}⚠${RESET} $1"; }
_fail() { echo -e "  ${RED}✗${RESET} $1"; }
_info() { echo -e "  ${DIM}$1${RESET}"; }

# Ticket tracking
declare -a TICKET_IDS=()

# ── Precondition checks ─────────────────────────────────────────────────────

_check_prerequisites() {
  _hdr "Prerequisites"

  if ! $CLI status >/dev/null 2>&1; then
    _fail "Proxym server not reachable at ${PROXYM_URL}"
    echo "    Start it with: proxym serve"
    exit 1
  fi
  _ok "Proxym server is running"

  if command -v node &>/dev/null; then
    _ok "Node.js $(node --version)"
  else
    _warn "Node.js not found — build/test steps will be skipped"
  fi

  $CLI tools show "$TOOL" >/dev/null 2>&1 \
    && _ok "Tool '${TOOL}' available" \
    || _warn "Tool '${TOOL}' not found — will use LLM fallback"
}

# ── Phase 1: Create project scaffold on disk ─────────────────────────────────

_create_project_scaffold() {
  _hdr "Phase 1 · Create Project on Disk"
  _info "Directory: ${PROJECT_DIR}"

  if [[ -f "${PROJECT_DIR}/package.json" ]]; then
    _warn "Project already exists (delete to start fresh)"
    return 0
  fi

  if $DRY_RUN; then
    _info "[dry-run] Would create project at ${PROJECT_DIR}"
    return 0
  fi

  mkdir -p "${PROJECT_DIR}"/{src,tests,.proxym}

  # Copy all template files
  cp "${TEMPLATES_DIR}/package.json"     "${PROJECT_DIR}/package.json"
  cp "${TEMPLATES_DIR}/tsconfig.json"    "${PROJECT_DIR}/tsconfig.json"
  cp "${TEMPLATES_DIR}/vitest.config.ts" "${PROJECT_DIR}/vitest.config.ts"
  cp "${TEMPLATES_DIR}/.gitignore"       "${PROJECT_DIR}/.gitignore"
  cp "${TEMPLATES_DIR}/README.md"        "${PROJECT_DIR}/README.md"
  cp "${TEMPLATES_DIR}/types.ts"         "${PROJECT_DIR}/src/types.ts"
  cp "${TEMPLATES_DIR}/store.ts"         "${PROJECT_DIR}/src/store.ts"
  cp "${TEMPLATES_DIR}/commands.ts"      "${PROJECT_DIR}/src/commands.ts"
  cp "${TEMPLATES_DIR}/format.ts"        "${PROJECT_DIR}/src/format.ts"
  cp "${TEMPLATES_DIR}/index.ts"         "${PROJECT_DIR}/src/index.ts"
  cp "${TEMPLATES_DIR}/store.test.ts"    "${PROJECT_DIR}/tests/store.test.ts"
  cp "${TEMPLATES_DIR}/commands.test.ts" "${PROJECT_DIR}/tests/commands.test.ts"
  cp "${SCRIPT_DIR}/spec.md"             "${PROJECT_DIR}/spec.md" 2>/dev/null || true

  # Initialize git
  if command -v git &>/dev/null && [[ ! -d "${PROJECT_DIR}/.git" ]]; then
    (cd "${PROJECT_DIR}" && git init -q && git add -A && git commit -q -m "Initial scaffold (proxym)") 2>/dev/null || true
  fi

  _ok "Project scaffold created ($(ls "${PROJECT_DIR}/src/"*.ts | wc -l) source files)"
}

# ── Phase 2: Register in proxym ──────────────────────────────────────────────

_register_project() {
  _hdr "Phase 2 · Register in Proxym"

  if $DRY_RUN; then
    _info "[dry-run] Would register ${PROJECT_DIR} as 'todo-app-ts'"
    return 0
  fi

  # Register project (idempotent — proxym handles duplicates)
  $CLI project add "${PROJECT_DIR}" --name todo-app-ts --tool "$TOOL" 2>&1 \
    && _ok "Project registered: todo-app-ts" \
    || _warn "Project may already exist (continuing)"

  # Verify it's there
  $CLI project show todo-app-ts 2>/dev/null || true
}

# ── Phase 3: Create sprint & tickets ────────────────────────────────────────

_create_sprint_and_tickets() {
  _hdr "Phase 3 · Create Sprint & Tickets"

  if $DRY_RUN; then
    _info "[dry-run] Would create sprint + 7 tickets"
    return 0
  fi

  # Create sprint
  $CLI sprint create --name "TODO App MVP" \
    --goal "Generate a fully working TypeScript TODO CLI app" 2>&1 || true
  _ok "Sprint created"

  # Create tickets — each one maps to a file in the TODO app
  local spec_ctx="Refer to spec.md in the project root for the full specification."
  local tid

  _info "Creating tickets..."

  tid=$($CLI ticket add "Implement TodoStore class in src/store.ts" \
    -p todo-app-ts -t "$TOOL" --priority high --type feature 2>&1 | grep -oE 'TKT-[A-F0-9]+' | head -1)
  TICKET_IDS+=("${tid:-FAILED}")
  _ok "  ${tid:-FAILED}  TodoStore"

  tid=$($CLI ticket add "Implement output formatters in src/format.ts" \
    -p todo-app-ts -t "$TOOL" --priority medium --type feature 2>&1 | grep -oE 'TKT-[A-F0-9]+' | head -1)
  TICKET_IDS+=("${tid:-FAILED}")
  _ok "  ${tid:-FAILED}  Formatters"

  tid=$($CLI ticket add "Implement CLI commands in src/commands.ts" \
    -p todo-app-ts -t "$TOOL" --priority high --type feature 2>&1 | grep -oE 'TKT-[A-F0-9]+' | head -1)
  TICKET_IDS+=("${tid:-FAILED}")
  _ok "  ${tid:-FAILED}  Commands"

  tid=$($CLI ticket add "Implement CLI entry point in src/index.ts" \
    -p todo-app-ts -t "$TOOL" --priority high --type feature 2>&1 | grep -oE 'TKT-[A-F0-9]+' | head -1)
  TICKET_IDS+=("${tid:-FAILED}")
  _ok "  ${tid:-FAILED}  CLI entry"

  tid=$($CLI ticket add "Write unit tests for TodoStore in tests/store.test.ts" \
    -p todo-app-ts -t "$TOOL" --priority high --type test 2>&1 | grep -oE 'TKT-[A-F0-9]+' | head -1)
  TICKET_IDS+=("${tid:-FAILED}")
  _ok "  ${tid:-FAILED}  Store tests"

  tid=$($CLI ticket add "Write integration tests in tests/commands.test.ts" \
    -p todo-app-ts -t "$TOOL" --priority medium --type test 2>&1 | grep -oE 'TKT-[A-F0-9]+' | head -1)
  TICKET_IDS+=("${tid:-FAILED}")
  _ok "  ${tid:-FAILED}  Integration tests"

  tid=$($CLI ticket add "Build and verify project compiles" \
    -p todo-app-ts --priority critical --type task 2>&1 | grep -oE 'TKT-[A-F0-9]+' | head -1)
  TICKET_IDS+=("${tid:-FAILED}")
  _ok "  ${tid:-FAILED}  Build verification (manual)"

  echo ""
  _ok "Created ${#TICKET_IDS[@]} tickets"

  # Show the board
  $CLI board 2>/dev/null || true
}

# ── Phase 4: Dispatch & wait ─────────────────────────────────────────────────

_dispatch_all() {
  _hdr "Phase 4 · Dispatch Tickets to AI Tools"

  if $SKIP_DISPATCH; then
    _info "Skipping dispatch (--skip-dispatch)"
    _info "Dispatch manually: proxym tools dispatch --ticket <id> --tool ${TOOL}"
    return 0
  fi

  if $DRY_RUN; then
    _info "[dry-run] Would dispatch ${#TICKET_IDS[@]} tickets to ${TOOL}"
    return 0
  fi

  # Ensure executor is running
  $CLI tools start 2>/dev/null || true

  local dispatched=0 failed=0

  for i in "${!TICKET_IDS[@]}"; do
    local tid="${TICKET_IDS[$i]}"
    [[ "$tid" == "FAILED" ]] && continue

    # Skip the last ticket (manual build verification)
    if [[ $i -eq $((${#TICKET_IDS[@]} - 1)) ]]; then
      _info "  Skipping manual ticket: ${tid}"
      continue
    fi

    _info "  Dispatching ${tid} to ${TOOL}..."
    if $CLI tools dispatch --ticket "$tid" --tool "$TOOL" --project-dir "$PROJECT_DIR" 2>&1; then
      dispatched=$((dispatched + 1))
      _ok "  ${tid} dispatched"
    else
      failed=$((failed + 1))
      _warn "  ${tid} dispatch failed"
    fi
  done

  _ok "Dispatched: ${dispatched} ok, ${failed} failed"

  # Wait for jobs to finish
  _info "Waiting for jobs to complete..."
  local attempts=0
  while [[ $attempts -lt 60 ]]; do
    sleep 5
    attempts=$((attempts + 1))
    local running
    running=$($CLI q 2>&1 | grep -cE "\s(running|queued)\s*$" || true)
    if [[ "$running" -eq 0 ]]; then
      break
    fi
    printf "\r  ${DIM}⏳ Waiting... (%ds)${RESET}" $((attempts * 5))
  done
  echo ""
  _ok "All jobs finished"
}

# ── Phase 5: Analyze results ─────────────────────────────────────────────────

_analyze_results() {
  _hdr "Phase 5 · Analyze Results"

  if $DRY_RUN || $SKIP_DISPATCH; then
    _info "[skipped] No dispatches to analyze"
    return 0
  fi

  for tid in "${TICKET_IDS[@]}"; do
    [[ "$tid" == "FAILED" ]] && continue
    echo ""
    $CLI analyze "$tid" 2>/dev/null || _warn "Could not analyze ${tid}"
  done
}

# ── Phase 6: Build & Verify ─────────────────────────────────────────────────

_verify_project() {
  _hdr "Phase 6 · Build & Verify"

  if $DRY_RUN; then
    _info "[dry-run] Would run npm install, build, test"
    return 0
  fi

  if ! command -v node &>/dev/null; then
    _warn "Node.js not installed — skipping"
    return 0
  fi

  local ok=true

  (cd "${PROJECT_DIR}" && npm install --no-fund --no-audit 2>&1 | tail -3) \
    && _ok "npm install" || { _warn "npm install failed"; ok=false; }

  (cd "${PROJECT_DIR}" && npx tsc --noEmit 2>&1) \
    && _ok "TypeScript: no errors" || { _warn "TypeScript errors found"; ok=false; }

  (cd "${PROJECT_DIR}" && npm run build 2>&1) \
    && _ok "Build succeeded" || { _warn "Build failed"; ok=false; }

  (cd "${PROJECT_DIR}" && npm test 2>&1) \
    && _ok "Tests passed" || { _warn "Tests failed"; ok=false; }

  if [[ -f "${PROJECT_DIR}/dist/index.js" ]]; then
    (cd "${PROJECT_DIR}" && node dist/index.js add "Smoke test" --priority high 2>&1) \
      && _ok "Smoke: add" || { _warn "Smoke: add failed"; ok=false; }
    (cd "${PROJECT_DIR}" && node dist/index.js list 2>&1) \
      && _ok "Smoke: list" || { _warn "Smoke: list failed"; ok=false; }
    (cd "${PROJECT_DIR}" && node dist/index.js stats 2>&1) \
      && _ok "Smoke: stats" || { _warn "Smoke: stats failed"; ok=false; }
  fi

  $ok && _ok "All verifications passed" || _warn "Some verifications failed"
}

# ── Summary ──────────────────────────────────────────────────────────────────

_print_summary() {
  echo ""
  echo -e "${BOLD}╔══════════════════════════════════════════════════════════════╗${RESET}"
  echo -e "${BOLD}║              Proxym Example — Complete                      ║${RESET}"
  echo -e "${BOLD}╠══════════════════════════════════════════════════════════════╣${RESET}"
  echo -e "${BOLD}║${RESET}  Project:  ${PROJECT_DIR}"
  echo -e "${BOLD}║${RESET}  Tickets:  ${#TICKET_IDS[@]}"
  echo -e "${BOLD}║${RESET}  Tool:     ${TOOL}"
  echo -e "${BOLD}║${RESET}"
  echo -e "${BOLD}║${RESET}  ${GREEN}The project is a standalone Node.js app on disk.${RESET}"
  echo -e "${BOLD}║${RESET}"
  echo -e "${BOLD}║${RESET}  Useful commands:"
  echo -e "${BOLD}║${RESET}    proxym board                    # kanban board"
  echo -e "${BOLD}║${RESET}    proxym ticket list -p todo-app-ts  # project tickets"
  echo -e "${BOLD}║${RESET}    proxym analyze <TKT-ID>         # check ticket result"
  echo -e "${BOLD}║${RESET}    proxym q                        # job queue status"
  echo -e "${BOLD}║${RESET}    proxym jobs                     # all jobs"
  echo -e "${BOLD}╚══════════════════════════════════════════════════════════════╝${RESET}"
}

# ── Main ─────────────────────────────────────────────────────────────────────

main() {
  echo -e "${BOLD}${CYAN}"
  echo "  ╔═══════════════════════════════════════════════════════════╗"
  echo "  ║  Proxym Example: TypeScript TODO App                     ║"
  echo "  ║  Automatic project generation via AI tool orchestration  ║"
  echo "  ╚═══════════════════════════════════════════════════════════╝"
  echo -e "${RESET}"

  if $CLEAN && [[ -d "${PROJECT_DIR}" ]]; then
    _warn "Removing existing project at ${PROJECT_DIR}..."
    rm -rf "${PROJECT_DIR}"
    _ok "Cleaned"
  fi

  _check_prerequisites
  _create_project_scaffold
  _register_project
  _create_sprint_and_tickets
  _dispatch_all
  _analyze_results
  _verify_project
  _print_summary
}

main
