#!/usr/bin/env bash
# smoke_test.sh — Curl every review_server endpoint, verify status codes + JSON.
#
# Usage:
#   bash tests/smoke_test.sh              # default: localhost:8430
#   bash tests/smoke_test.sh 8431         # custom port
#
# Prerequisites:
#   1. python tests/seed_test_db.py --clean
#   2. python -m editors.review_server (running on PORT)

set -euo pipefail

PORT="${1:-8430}"
BASE="http://127.0.0.1:${PORT}"
PASS=0
FAIL=0
WARN=0
RESULTS=()

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

green()  { printf "\033[32m%s\033[0m" "$1"; }
red()    { printf "\033[31m%s\033[0m" "$1"; }
yellow() { printf "\033[33m%s\033[0m" "$1"; }

check() {
    local method="$1" url="$2" expect_status="$3" label="$4"
    shift 4
    local extra_args=()
    if [ $# -gt 0 ]; then extra_args=("$@"); fi

    local response status body
    if [ ${#extra_args[@]} -eq 0 ]; then
        response=$(curl -s -w "\n%{http_code}" -X "$method" "$url" 2>&1)
    else
        response=$(curl -s -w "\n%{http_code}" -X "$method" "${extra_args[@]}" "$url" 2>&1)
    fi
    status=$(echo "$response" | tail -1)
    body=$(echo "$response" | sed '$d')

    if [ "$status" = "$expect_status" ]; then
        # Verify JSON if status is 2xx
        if [[ "$expect_status" =~ ^2 ]]; then
            if echo "$body" | python3 -m json.tool > /dev/null 2>&1; then
                PASS=$((PASS + 1))
                RESULTS+=("$(green "PASS") $label ($status)")
            else
                WARN=$((WARN + 1))
                RESULTS+=("$(yellow "WARN") $label ($status but invalid JSON)")
            fi
        else
            PASS=$((PASS + 1))
            RESULTS+=("$(green "PASS") $label ($status)")
        fi
    else
        FAIL=$((FAIL + 1))
        RESULTS+=("$(red "FAIL") $label (expected $expect_status, got $status)")
    fi
}

# JSON POST helper
json_post() {
    local url="$1" data="$2" expect_status="$3" label="$4"
    check POST "$url" "$expect_status" "$label" \
        -H "Content-Type: application/json" -d "$data"
}

# JSON PATCH helper
json_patch() {
    local url="$1" data="$2" expect_status="$3" label="$4"
    local response status body
    response=$(curl -s -w "\n%{http_code}" -X PATCH \
        -H "Content-Type: application/json" -d "$data" "$url" 2>&1)
    status=$(echo "$response" | tail -1)
    body=$(echo "$response" | sed '$d')

    if [ "$status" = "$expect_status" ]; then
        if echo "$body" | python3 -m json.tool > /dev/null 2>&1; then
            PASS=$((PASS + 1))
            RESULTS+=("$(green "PASS") $label ($status)")
        else
            WARN=$((WARN + 1))
            RESULTS+=("$(yellow "WARN") $label ($status but invalid JSON)")
        fi
    else
        FAIL=$((FAIL + 1))
        RESULTS+=("$(red "FAIL") $label (expected $expect_status, got $status)")
    fi
}

echo ""
echo "  ╔═══════════════════════════════════════════════════╗"
echo "  ║  Starsend Smoke Test — ${BASE}  ║"
echo "  ╚═══════════════════════════════════════════════════╝"
echo ""

# ── 1. Server connectivity ────────────────────────────────────────────
echo "  ── Phase 1: Server Connectivity ──"

check GET "${BASE}/" 200 "GET / (review.html)"
check GET "${BASE}/console" 200 "GET /console (console.html)"

# ── 2. GET endpoints ──────────────────────────────────────────────────
echo "  ── Phase 2: GET Endpoints ──"

check GET "${BASE}/api/projects" 200 "GET /api/projects"
check GET "${BASE}/api/episodes" 200 "GET /api/episodes"
check GET "${BASE}/api/bible" 200 "GET /api/bible"
check GET "${BASE}/api/budget" 200 "GET /api/budget"
check GET "${BASE}/api/board" 200 "GET /api/board"
check GET "${BASE}/api/dailies" 200 "GET /api/dailies"

# Episode-specific endpoints
check GET "${BASE}/api/manifest/ep_999" 200 "GET /api/manifest/ep_999"
check GET "${BASE}/api/board/EP999" 200 "GET /api/board/EP999"
check GET "${BASE}/api/stale-check/ep_001" 200 "GET /api/stale-check/ep_001"

# ── 3. POST endpoints — Dailies actions ───────────────────────────────
echo "  ── Phase 3: POST Endpoints — Dailies ──"

# Approve previs_generated shot (SH03) → should advance to previs_approved
json_post "${BASE}/api/dailies/approve" \
    '{"shot_id": "EP999_SH03"}' 200 \
    "POST /api/dailies/approve (SH03 previs_generated → previs_approved)"

# Reject video_ready shot (SH02) → should re-queue to video_pending
json_post "${BASE}/api/dailies/reject" \
    '{"shot_id": "EP999_SH02"}' 200 \
    "POST /api/dailies/reject (SH02 video_ready → video_pending)"

# Override prompt for failed shot (SH01)
json_post "${BASE}/api/dailies/override" \
    '{"shot_id": "EP999_SH01", "prompt": "Ruined orbital station, amber starlight, debris field — corrected prompt"}' 200 \
    "POST /api/dailies/override (SH01 prompt override + re-queue)"

# Reroute shot to different model
json_post "${BASE}/api/dailies/reroute" \
    '{"shot_id": "EP999_SH05", "model": "kling-3.0", "pipeline": "t2v"}' 200 \
    "POST /api/dailies/reroute (SH05 seeddance → kling)"

# Select take for multi-take shot
json_post "${BASE}/api/dailies/select-take" \
    '{"shot_id": "EP999_SH04", "take_id": "take_2"}' 200 \
    "POST /api/dailies/select-take (SH04 → take_2)"

# Abandon a shot
json_post "${BASE}/api/dailies/abandon" \
    '{"shot_id": "EP999_SH06"}' 200 \
    "POST /api/dailies/abandon (SH06)"

# ── 4. POST endpoints — Launch batch ─────────────────────────────────
echo "  ── Phase 4: POST Endpoints — Launch Batch ──"

json_post "${BASE}/api/launch-batch" \
    '{"episode_id": "EP999"}' 200 \
    "POST /api/launch-batch (preflight + cost estimate)"

json_post "${BASE}/api/launch-batch/confirm" \
    '{"episode_id": "EP999"}' 200 \
    "POST /api/launch-batch/confirm (queue shots)"

# ── 5. PATCH endpoints ───────────────────────────────────────────────
echo "  ── Phase 5: PATCH Endpoints ──"

json_patch "${BASE}/api/bible/character/nonexistent_char" \
    '{"description": "test"}' 404 \
    "PATCH /api/bible/character/nonexistent (expect 404)"

# ── 6. Error handling ────────────────────────────────────────────────
echo "  ── Phase 6: Error Handling ──"

check GET "${BASE}/api/manifest/ep_000" 404 "GET /api/manifest/ep_000 (nonexistent → 404)"
json_post "${BASE}/api/dailies/approve" '{}' 400 "POST /api/dailies/approve (no shot_id → 400)"
json_post "${BASE}/api/launch-batch" '{}' 400 "POST /api/launch-batch (no episode_id → 400)"

# ── 7. Verify state mutations ────────────────────────────────────────
echo "  ── Phase 7: State Verification ──"

# Re-fetch dailies to verify mutations took effect
response=$(curl -s "${BASE}/api/dailies")
dailies_count=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('total', -1))" 2>/dev/null || echo "-1")
if [ "$dailies_count" != "-1" ]; then
    PASS=$((PASS + 1))
    RESULTS+=("$(green "PASS") Dailies queue has ${dailies_count} items after mutations")
else
    FAIL=$((FAIL + 1))
    RESULTS+=("$(red "FAIL") Could not parse dailies response after mutations")
fi

# Re-fetch board to verify EP999 shows up
response=$(curl -s "${BASE}/api/board/EP999")
ep999_total=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('summary',{}).get('total_shots', -1))" 2>/dev/null || echo "-1")
if [ "$ep999_total" = "6" ]; then
    PASS=$((PASS + 1))
    RESULTS+=("$(green "PASS") Board EP999 shows 6 total shots")
else
    WARN=$((WARN + 1))
    RESULTS+=("$(yellow "WARN") Board EP999 total_shots=${ep999_total} (expected 6)")
fi

# ── Results ──────────────────────────────────────────────────────────
echo ""
echo "  ╔═══════════════════════════════════════════════════╗"
echo "  ║  Results                                          ║"
echo "  ╚═══════════════════════════════════════════════════╝"
echo ""

for result in "${RESULTS[@]}"; do
    echo "    $result"
done

echo ""
echo "  ─────────────────────────────────────────────────────"
printf "    $(green "PASS"): %d   $(red "FAIL"): %d   $(yellow "WARN"): %d   Total: %d\n" \
    "$PASS" "$FAIL" "$WARN" "$((PASS + FAIL + WARN))"
echo "  ─────────────────────────────────────────────────────"
echo ""

if [ "$FAIL" -gt 0 ]; then
    exit 1
fi
