#!/usr/bin/env bash
###############################################################################
# run.sh — Proxym Example: Multi-Project with Sprints
#
# Demonstrates managing 2 projects simultaneously with sprints:
#   Project A: "calculator" — Python calculator module + tests
#   Project B: "greeter"    — Python greeter CLI + tests
#
# Each project gets its own sprint and 2 tickets.
# Generated code lands in examples/multi-project/src/<project>/
#
# Usage:
#   bash examples/multi-project/run.sh
#   bash examples/multi-project/run.sh --dry-run
#   bash examples/multi-project/run.sh --tool claude-code
#
# Prerequisites:
#   - proxym server running (proxym serve)
###############################################################################
set -euo pipefail

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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROXYM_URL="${PROXYM_URL:-${DEFAULT_PROXY_URL:-http://localhost:4000}}"
TOOL="${TOOL:-aider}"
DRY_RUN=false
WAIT_TIMEOUT=120

# Project directories — inside examples/multi-project/src/
PROJECT_A_DIR="${SCRIPT_DIR}/src/calculator"
PROJECT_B_DIR="${SCRIPT_DIR}/src/greeter"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --dry-run)  DRY_RUN=true; shift ;;
    --tool)     TOOL="$2"; shift 2 ;;
    --proxy)    PROXYM_URL="$2"; shift 2 ;;
    --clean)
      echo "Cleaning generated files..."
      rm -rf "${SCRIPT_DIR}/src/calculator/"* "${SCRIPT_DIR}/src/greeter/"*
      echo "Done."
      shift
      ;;
    --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"

# ── Helpers ──────────────────────────────────────────────────────────────────

GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'
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}"; }

# ── Load .env from repo root ────────────────────────────────────────────────

_load_env() {
  local env_file
  # Walk up from SCRIPT_DIR to find .env at repo root
  env_file="$(cd "$SCRIPT_DIR" && git rev-parse --show-toplevel 2>/dev/null)/.env"
  [[ -z "$env_file" ]] && env_file="${SCRIPT_DIR}/../../.env"
  if [[ -f "$env_file" ]]; then
    # Export only KEY=VALUE lines (skip comments, empty lines)
    set -a
    # shellcheck disable=SC1090
    source <(grep -E '^[A-Z_]+=.+' "$env_file" | grep -v '^#')
    set +a
    _ok "Loaded .env from ${env_file}"
  else
    _warn "No .env found (looked for ${env_file})"
  fi
}

# ── API Key helpers ──────────────────────────────────────────────────────────

_required_api_key_for_tool() {
  local tool="$1"
  case "$tool" in
    aider|claude-code|cline)  echo "ANTHROPIC_API_KEY" ;;
    cursor|windsurf|vscode)   echo "OPENAI_API_KEY" ;;
    *)                        echo "ANTHROPIC_API_KEY" ;;
  esac
}

_ensure_api_key() {
  local tool="$1"
  local key_name
  key_name=$(_required_api_key_for_tool "$tool")
  local key_val="${!key_name:-}"

  # Already set — nothing to do
  if [[ -n "$key_val" ]]; then
    _ok "${key_name} is set (${#key_val} chars)"
    return 0
  fi

  _warn "${key_name} is not set — required by tool '${tool}'"

  # ── Option A: Interactive terminal — prompt directly ──
  if [[ -t 0 ]]; then
    echo ""
    echo -e "  ${BOLD}The tool '${tool}' needs ${key_name} to generate code.${RESET}"
    echo -e "  You can paste it now, or press Enter to create a human ticket instead."
    echo ""
    read -rp "  ${key_name}= " user_key
    if [[ -n "$user_key" ]]; then
      export "${key_name}=${user_key}"
      _ok "${key_name} set from interactive input"
      return 0
    fi
  fi

  # ── Option B: Create a human ticket and wait for the response ──
  _info "Creating a human ticket to collect ${key_name}..."

  local ticket_out
  ticket_out=$($CLI ticket add \
    "Provide ${key_name} for tool '${tool}'" \
    -t human \
    --priority high --type task 2>&1)
  local human_tid
  human_tid=$(echo "$ticket_out" | _extract_tid)

  if [[ -z "$human_tid" ]]; then
    _fail "Could not create human ticket. Please set ${key_name} manually."
    echo "    export ${key_name}=sk-..."
    echo "    Or add it to .env and re-run."
    exit 1
  fi

  # Add an instructional comment
  $CLI ticket comment "$human_tid" \
    --author system \
    --content "Please reply with the API key value for ${key_name}. Add a comment to this ticket with just the key (e.g. sk-ant-...). The script will pick it up automatically and continue." \
    2>/dev/null || true

  _ok "Human ticket created: ${human_tid}"
  echo ""
  echo -e "  ${BOLD}Waiting for human input...${RESET}"
  echo -e "  Add the API key as a comment to ticket ${human_tid}:"
  echo -e "    ${DIM}proxym ticket comment ${human_tid} --author human --content 'sk-ant-...'${RESET}"
  echo -e "    ${DIM}Or use the Dashboard → Tickets → ${human_tid} → Add Comment${RESET}"
  echo ""

  # Poll for a human comment (skip system comments)
  local poll_elapsed=0
  local poll_max=600  # 10 minutes
  while [[ $poll_elapsed -lt $poll_max ]]; do
    local comments
    comments=$($CLI ticket show "$human_tid" 2>&1 | grep -A1 '\[human\]' | tail -1 || true)
    # Also check via JSON for robustness
    if [[ -z "$comments" ]]; then
      comments=$($CLI ticket show "$human_tid" --yaml 2>&1 \
        | grep -oP '(?<=content: ).*' \
        | grep -vE '^(Please reply|Auto-assigned)' \
        | head -1 || true)
    fi

    # Extract something that looks like an API key from the comment
    local found_key
    found_key=$(echo "$comments" | grep -oE 'sk-[A-Za-z0-9_-]{20,}' | head -1 || true)
    if [[ -n "$found_key" ]]; then
      export "${key_name}=${found_key}"
      _ok "${key_name} received from human ticket ${human_tid}"
      # Mark ticket done
      $CLI ticket update "$human_tid" --status done 2>/dev/null || true
      return 0
    fi

    sleep 5
    poll_elapsed=$((poll_elapsed + 5))
    printf "\r  ${DIM}⏳ Waiting for API key... (%ds/${poll_max}s) — add comment to ${human_tid}${RESET}" "$poll_elapsed"
  done

  echo ""
  _fail "Timeout waiting for ${key_name} via ticket ${human_tid}"
  echo "    Set it manually and re-run:"
  echo "    export ${key_name}=sk-..."
  exit 1
}

_extract_tid() { grep -oE 'TKT-[A-F0-9]+' | head -1; }
_extract_sprid() { grep -oE 'SPR-[A-F0-9]+' | head -1; }

_wait_for_jobs() {
  local max_wait="$1" elapsed=0
  while [[ $elapsed -lt $max_wait ]]; do
    local active
    active=$($CLI q 2>&1 | grep -cE "\s(running|queued)\s*$" || true)
    [[ "$active" -eq 0 ]] && return 0
    sleep 3
    elapsed=$((elapsed + 3))
    printf "\r  ${DIM}⏳ Waiting... (%ds/${max_wait}s)${RESET}" "$elapsed"
  done
  echo ""
  return 1
}

# ── Banner ───────────────────────────────────────────────────────────────────

echo -e "${BOLD}${CYAN}"
echo "  ╔═══════════════════════════════════════════════════════════╗"
echo "  ║  Proxym: Multi-Project Example                          ║"
echo "  ║  2 projects × 2 tickets × sprints                       ║"
echo "  ╚═══════════════════════════════════════════════════════════╝"
echo -e "${RESET}"

# ── Step 1: Prerequisites ────────────────────────────────────────────────────

_hdr "Step 1 · Prerequisites"

if $DRY_RUN; then
  _info "[dry-run] Would check server at ${PROXYM_URL}"
  _info "[dry-run] Would load .env and check API keys"
else
  # Load .env first — provides API keys and DEFAULT_PROXY_URL
  _load_env

  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 running"

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

  # Ensure the required API key is available before we start creating tickets
  _ensure_api_key "$TOOL"
fi

# ── Step 2: Create project directories ───────────────────────────────────────

_hdr "Step 2 · Create Project Directories"

if $DRY_RUN; then
  _info "[dry-run] Would create ${PROJECT_A_DIR}/"
  _info "[dry-run] Would create ${PROJECT_B_DIR}/"
else
  mkdir -p "${PROJECT_A_DIR}" "${PROJECT_B_DIR}"
  _ok "calculator: ${PROJECT_A_DIR}"
  _ok "greeter:    ${PROJECT_B_DIR}"
fi

# ── Step 3: Register both projects ──────────────────────────────────────────

_hdr "Step 3 · Register Projects"

if $DRY_RUN; then
  _info "[dry-run] Would register 'calculator' and 'greeter'"
else
  $CLI project add "${PROJECT_A_DIR}" --name calculator --tool "$TOOL" 2>&1 \
    && _ok "Project 'calculator' registered" \
    || _warn "calculator may already exist"

  $CLI project add "${PROJECT_B_DIR}" --name greeter --tool "$TOOL" 2>&1 \
    && _ok "Project 'greeter' registered" \
    || _warn "greeter may already exist"
fi

# ── Step 4: Create sprints ──────────────────────────────────────────────────

_hdr "Step 4 · Create Sprints"

SPRINT_A=""
SPRINT_B=""

if $DRY_RUN; then
  _info "[dry-run] Would create sprint 'Calculator MVP'"
  _info "[dry-run] Would create sprint 'Greeter MVP'"
else
  local_out=$($CLI sprint create --name "Calculator MVP" \
    --goal "Python calculator module with tests" 2>&1)
  SPRINT_A=$(echo "$local_out" | _extract_sprid)
  _ok "Sprint A: ${SPRINT_A:-created}"

  local_out=$($CLI sprint create --name "Greeter MVP" \
    --goal "Python greeter CLI with tests" 2>&1)
  SPRINT_B=$(echo "$local_out" | _extract_sprid)
  _ok "Sprint B: ${SPRINT_B:-created}"

  # Show sprints
  $CLI sprint list 2>/dev/null || true
fi

# ── Step 5: Create tickets ──────────────────────────────────────────────────

_hdr "Step 5 · Create Tickets"

declare -a TIDS_A=()
declare -a TIDS_B=()

if $DRY_RUN; then
  _info "[dry-run] Would create 2 tickets for calculator"
  _info "[dry-run] Would create 2 tickets for greeter"
else
  # ── Calculator tickets ──
  _info "Calculator project:"

  local_out=$($CLI ticket add \
    "Create calculator.py with add, subtract, multiply, divide functions. Include type hints, docstrings, and handle division by zero with ValueError." \
    -p calculator -t "$TOOL" --priority high --type feature \
    ${SPRINT_A:+--sprint "$SPRINT_A"} 2>&1)
  local_tid=$(echo "$local_out" | _extract_tid)
  TIDS_A+=("${local_tid:-FAILED}")
  _ok "  ${local_tid:-FAILED}  calculator.py (implementation)"

  local_out=$($CLI ticket add \
    "Create test_calculator.py with pytest tests for all calculator functions (add, subtract, multiply, divide). Include edge cases: division by zero, large numbers, negative numbers, floats." \
    -p calculator -t "$TOOL" --priority high --type test \
    ${SPRINT_A:+--sprint "$SPRINT_A"} 2>&1)
  local_tid=$(echo "$local_out" | _extract_tid)
  TIDS_A+=("${local_tid:-FAILED}")
  _ok "  ${local_tid:-FAILED}  test_calculator.py (tests)"

  # ── Greeter tickets ──
  _info "Greeter project:"

  local_out=$($CLI ticket add \
    "Create greeter.py with a Greeter class that has methods: hello(name) returns greeting string, goodbye(name) returns farewell string, formal(name, title) returns formal greeting. Include type hints and docstrings." \
    -p greeter -t "$TOOL" --priority high --type feature \
    ${SPRINT_B:+--sprint "$SPRINT_B"} 2>&1)
  local_tid=$(echo "$local_out" | _extract_tid)
  TIDS_B+=("${local_tid:-FAILED}")
  _ok "  ${local_tid:-FAILED}  greeter.py (implementation)"

  local_out=$($CLI ticket add \
    "Create test_greeter.py with pytest tests for the Greeter class. Test hello, goodbye, and formal methods with various inputs including empty strings and special characters." \
    -p greeter -t "$TOOL" --priority high --type test \
    ${SPRINT_B:+--sprint "$SPRINT_B"} 2>&1)
  local_tid=$(echo "$local_out" | _extract_tid)
  TIDS_B+=("${local_tid:-FAILED}")
  _ok "  ${local_tid:-FAILED}  test_greeter.py (tests)"

  echo ""
  _ok "Created ${#TIDS_A[@]} + ${#TIDS_B[@]} = $((${#TIDS_A[@]} + ${#TIDS_B[@]})) tickets"

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

# ── Step 6: Dispatch & analyze each ticket ───────────────────────────────────

_dispatch_and_analyze() {
  local tid="$1" project_dir="$2" label="$3"
  [[ "$tid" == "FAILED" ]] && { _warn "Skipping FAILED ticket"; return 1; }

  _info "Dispatching ${tid} (${label}) to ${TOOL}..."
  if ! $CLI tools dispatch --ticket "$tid" --tool "$TOOL" --project-dir "$project_dir" 2>&1; then
    _warn "Dispatch failed for ${tid}"
    return 1
  fi
  _ok "Dispatched: ${tid}"

  _info "Waiting for job..."
  if _wait_for_jobs "$WAIT_TIMEOUT"; then
    echo ""
    _ok "Job completed"
  else
    _warn "Timeout — job may still be running"
  fi

  echo ""
  $CLI analyze "$tid" 2>/dev/null || _warn "Could not analyze ${tid}"
  return 0
}

_hdr "Step 6 · Dispatch & Analyze"

if $DRY_RUN; then
  _info "[dry-run] Would dispatch 4 tickets and analyze each"
else
  _info "── Calculator ──"
  for i in "${!TIDS_A[@]}"; do
    _dispatch_and_analyze "${TIDS_A[$i]}" "$PROJECT_A_DIR" "calculator #$((i+1))"
    echo ""
  done

  _info "── Greeter ──"
  for i in "${!TIDS_B[@]}"; do
    _dispatch_and_analyze "${TIDS_B[$i]}" "$PROJECT_B_DIR" "greeter #$((i+1))"
    echo ""
  done
fi

# ── Step 7: Verify project filters ──────────────────────────────────────────

_hdr "Step 7 · Verify Project Isolation"

if $DRY_RUN; then
  _info "[dry-run] Would verify ticket list --project filter"
else
  echo ""
  _info "Calculator tickets:"
  $CLI ticket list --project calculator 2>/dev/null || true
  echo ""
  _info "Greeter tickets:"
  $CLI ticket list --project greeter 2>/dev/null || true
fi

# ── Step 8: Sprint status ────────────────────────────────────────────────────

_hdr "Step 8 · Sprint Status"

if $DRY_RUN; then
  _info "[dry-run] Would show sprint list"
else
  $CLI sprint list 2>/dev/null || true

  # Show sprint details if we have IDs
  if [[ -n "$SPRINT_A" ]]; then
    echo ""
    $CLI sprint show "$SPRINT_A" 2>/dev/null || true
  fi
  if [[ -n "$SPRINT_B" ]]; then
    echo ""
    $CLI sprint show "$SPRINT_B" 2>/dev/null || true
  fi
fi

# ── Step 9: Check generated files ────────────────────────────────────────────

_hdr "Step 9 · Generated Files"

if $DRY_RUN; then
  _info "[dry-run] Would list files in src/calculator/ and src/greeter/"
else
  _info "Calculator (${PROJECT_A_DIR}):"
  if ls "${PROJECT_A_DIR}"/*.py 2>/dev/null | head -1 >/dev/null 2>&1; then
    ls -la "${PROJECT_A_DIR}"/*.py 2>/dev/null | sed 's/^/    /'
  else
    _warn "  No .py files generated (dispatch may have failed)"
  fi

  echo ""
  _info "Greeter (${PROJECT_B_DIR}):"
  if ls "${PROJECT_B_DIR}"/*.py 2>/dev/null | head -1 >/dev/null 2>&1; then
    ls -la "${PROJECT_B_DIR}"/*.py 2>/dev/null | sed 's/^/    /'
  else
    _warn "  No .py files generated (dispatch may have failed)"
  fi
fi

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

echo ""
echo -e "${BOLD}╔══════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${BOLD}║              Multi-Project Example — Complete               ║${RESET}"
echo -e "${BOLD}╠══════════════════════════════════════════════════════════════╣${RESET}"
echo -e "${BOLD}║${RESET}  Projects:  calculator, greeter"
echo -e "${BOLD}║${RESET}  Sprints:   ${SPRINT_A:-n/a}, ${SPRINT_B:-n/a}"
echo -e "${BOLD}║${RESET}  Tickets:   ${#TIDS_A[@]} + ${#TIDS_B[@]} = $((${#TIDS_A[@]} + ${#TIDS_B[@]}))"
echo -e "${BOLD}║${RESET}  Tool:      ${TOOL}"
echo -e "${BOLD}║${RESET}  Code in:   examples/multi-project/src/"
echo -e "${BOLD}║${RESET}"
echo -e "${BOLD}║${RESET}  Useful commands:"
echo -e "${BOLD}║${RESET}    proxym board                         ${DIM}# kanban${RESET}"
echo -e "${BOLD}║${RESET}    proxym ticket list --project calculator  ${DIM}# per-project${RESET}"
echo -e "${BOLD}║${RESET}    proxym ticket list --project greeter     ${DIM}# per-project${RESET}"
echo -e "${BOLD}║${RESET}    proxym sprint list                   ${DIM}# sprints${RESET}"
for tid in "${TIDS_A[@]}" "${TIDS_B[@]}"; do
  [[ "$tid" == "FAILED" ]] && continue
  echo -e "${BOLD}║${RESET}    proxym analyze ${tid}          ${DIM}# ticket result${RESET}"
done
echo -e "${BOLD}╚══════════════════════════════════════════════════════════════╝${RESET}"
echo ""
_ok "Done!"
