#!/usr/bin/env bash
# =============================================================================
# Changemaker Lite — Deployment Test Suite
#
# Verifies that all core services are running and responding correctly.
# Run after install or upgrade to validate the deployment.
#
# Usage:
#   bash scripts/test-deployment.sh [OPTIONS]
#
# Options:
#   --wait SECS    Wait for services before testing (default: 0)
#   --domain DOM   Test tunnel connectivity for this domain
#   --quiet        Only show failures and summary
#   --help         Show this help
# =============================================================================
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WAIT_SECS=0
TEST_DOMAIN=""
QUIET=false

# Colors
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
  RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m'
  BOLD='\033[1m' NC='\033[0m'
else
  RED='' GREEN='' YELLOW='' BOLD='' NC=''
fi

while [[ $# -gt 0 ]]; do
  case "$1" in
    --wait)   WAIT_SECS="$2"; shift 2 ;;
    --domain) TEST_DOMAIN="$2"; shift 2 ;;
    --quiet)  QUIET=true; shift ;;
    --help|-h)
      sed -n '2,16p' "$0" | grep '^#' | sed 's/^# \?//'
      exit 0 ;;
    *) shift ;;
  esac
done

PASS=0 FAIL=0 WARN=0 SKIP=0

pass() { PASS=$((PASS+1)); [[ "$QUIET" == "false" ]] && echo -e "  ${GREEN}PASS${NC} $1"; }
fail() { FAIL=$((FAIL+1)); echo -e "  ${RED}FAIL${NC} $1"; }
warn() { WARN=$((WARN+1)); [[ "$QUIET" == "false" ]] && echo -e "  ${YELLOW}WARN${NC} $1"; }
skip() { SKIP=$((SKIP+1)); [[ "$QUIET" == "false" ]] && echo -e "  ${YELLOW}SKIP${NC} $1"; }

# Load .env
if [[ -f "$SCRIPT_DIR/.env" ]]; then
  source <(grep -E '^(API_PORT|ADMIN_PORT|MEDIA_API_PORT|DOMAIN|ENABLE_|INITIAL_ADMIN_EMAIL)=' "$SCRIPT_DIR/.env" 2>/dev/null || true)
fi
API_PORT="${API_PORT:-4000}"
ADMIN_PORT="${ADMIN_PORT:-3000}"
MEDIA_API_PORT="${MEDIA_API_PORT:-4100}"
DOMAIN="${DOMAIN:-cmlite.org}"
[[ -n "$TEST_DOMAIN" ]] && DOMAIN="$TEST_DOMAIN"

cd "$SCRIPT_DIR"

echo -e "${BOLD}Changemaker Lite — Deployment Test${NC}"
echo ""

# Wait if requested
if [[ "$WAIT_SECS" -gt 0 ]]; then
  echo "Waiting ${WAIT_SECS}s for services to start..."
  sleep "$WAIT_SECS"
fi

# ─── Core Health ─────────────────────────────────────────────────────────
echo -e "${BOLD}Core Health${NC}"

HEALTH=$(curl -sf "http://localhost:${API_PORT}/api/health" 2>/dev/null || echo "")
if echo "$HEALTH" | grep -q '"healthy"'; then
  pass "API health"
else
  fail "API health (${HEALTH:-no response})"
fi

MEDIA=$(curl -sf "http://localhost:${MEDIA_API_PORT}/health" 2>/dev/null || echo "")
if echo "$MEDIA" | grep -q '"ok"'; then
  pass "Media API health"
else
  fail "Media API health"
fi

ADMIN_CODE=$(curl -sf -o /dev/null -w "%{http_code}" "http://localhost:${ADMIN_PORT}/" 2>/dev/null || echo "0")
if [[ "$ADMIN_CODE" == "200" ]]; then
  pass "Admin GUI (HTTP $ADMIN_CODE)"
else
  fail "Admin GUI (HTTP $ADMIN_CODE)"
fi

# ─── Authentication ──────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Authentication${NC}"

# Get admin email from .env
ADMIN_EMAIL="${INITIAL_ADMIN_EMAIL:-admin@${DOMAIN}}"
# Try to login — write payload to file to avoid ! escaping
LOGIN_FILE=$(mktemp)
# Read password from .env directly (avoid bash expansion issues with !)
ADMIN_PW=$(grep "^INITIAL_ADMIN_PASSWORD=" "$SCRIPT_DIR/.env" 2>/dev/null | head -1 | cut -d= -f2-)
printf '{"email":"%s","password":"%s"}' "$ADMIN_EMAIL" "$ADMIN_PW" > "$LOGIN_FILE"

TOKEN=$(curl -sf -X POST "http://localhost:${API_PORT}/api/auth/login" \
  -H "Content-Type: application/json" -d "@$LOGIN_FILE" 2>/dev/null \
  | python3 -c "import sys,json; print(json.load(sys.stdin).get('accessToken',''))" 2>/dev/null || echo "")
rm -f "$LOGIN_FILE"

if [[ -n "$TOKEN" ]]; then
  pass "Admin login"
else
  fail "Admin login ($ADMIN_EMAIL)"
fi

# ─── Authenticated Endpoints ─────────────────────────────────────────────
echo ""
echo -e "${BOLD}Authenticated API${NC}"

if [[ -n "$TOKEN" ]]; then
  AUTH="Authorization: Bearer $TOKEN"
  for ep in "/api/settings" "/api/users" "/api/dashboard/summary" "/api/services/status"; do
    CODE=$(curl -sf -o /dev/null -w "%{http_code}" "http://localhost:${API_PORT}${ep}" -H "$AUTH" 2>/dev/null || echo "0")
    if [[ "$CODE" == "200" ]]; then
      pass "GET $ep"
    else
      fail "GET $ep (HTTP $CODE)"
    fi
  done
else
  skip "Authenticated endpoints (no token)"
fi

# ─── Public Endpoints ────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Public API${NC}"

for ep in "/api/campaigns/public" "/api/map/shifts/public" "/api/pages/listed" \
          "/api/donation-pages" "/api/homepage" "/api/qr?text=test" \
          "/api/petitions/public" "/api/payments/plans" "/api/payments/products" \
          "/api/map/cuts/public"; do
  CODE=$(curl -sf -o /dev/null -w "%{http_code}" "http://localhost:${API_PORT}${ep}" 2>/dev/null || echo "0")
  if [[ "$CODE" == "200" ]]; then
    pass "GET $ep"
  else
    fail "GET $ep (HTTP $CODE)"
  fi
done

# ─── Supporting Services ─────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Supporting Services${NC}"

declare -A SERVICES=(
  [gitea]=3030 [nocodb]=8091 [listmonk]=9001 [n8n]=5678
  [homepage]=3010 [excalidraw]=8090 [vaultwarden]=8445
  [mailhog]=8025 [mkdocs-dev]=4003 [mkdocs-static]=4004 [mini-qr]=8089
)

for svc in "${!SERVICES[@]}"; do
  port=${SERVICES[$svc]}
  CODE=$(curl -sf -o /dev/null -w "%{http_code}" --max-time 5 "http://localhost:${port}/" 2>/dev/null || echo "0")
  if [[ "$CODE" == "200" || "$CODE" == "302" ]]; then
    pass "$svc (:$port)"
  else
    fail "$svc (:$port) (HTTP $CODE)"
  fi
done

# ─── Nginx Proxy ─────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Nginx Proxy${NC}"

NGINX_HEALTH=$(docker compose ps nginx --format '{{.Health}}' 2>/dev/null || echo "unknown")
if [[ "$NGINX_HEALTH" == "healthy" ]]; then
  pass "Nginx container healthy"

  API_PROXY=$(curl -sf -H "Host: api.${DOMAIN}" "http://localhost:80/api/health" 2>/dev/null || echo "")
  if echo "$API_PROXY" | grep -q '"healthy"'; then
    pass "Nginx -> API proxy"
  else
    fail "Nginx -> API proxy"
  fi

  ADMIN_PROXY=$(curl -sf -o /dev/null -w "%{http_code}" -H "Host: app.${DOMAIN}" "http://localhost:80/" 2>/dev/null || echo "0")
  if [[ "$ADMIN_PROXY" == "200" ]]; then
    pass "Nginx -> Admin proxy"
  else
    fail "Nginx -> Admin proxy (HTTP $ADMIN_PROXY)"
  fi
else
  fail "Nginx container ($NGINX_HEALTH)"
fi

# ─── Tunnel (optional) ──────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Tunnel${NC}"

NEWT_STATUS=$(docker compose ps newt --format '{{.Status}}' 2>/dev/null || echo "")
if echo "$NEWT_STATUS" | grep -q "Up"; then
  pass "Newt container running"

  TUNNEL_API=$(curl -sf -o /dev/null -w "%{http_code}" --max-time 10 "https://api.${DOMAIN}/api/health" 2>/dev/null || echo "0")
  if [[ "$TUNNEL_API" == "200" ]]; then
    pass "Tunnel -> api.${DOMAIN}"
  else
    warn "Tunnel -> api.${DOMAIN} (HTTP $TUNNEL_API)"
  fi

  TUNNEL_APP=$(curl -sf -o /dev/null -w "%{http_code}" --max-time 10 "https://app.${DOMAIN}/" 2>/dev/null || echo "0")
  if [[ "$TUNNEL_APP" == "200" ]]; then
    pass "Tunnel -> app.${DOMAIN}"
  else
    warn "Tunnel -> app.${DOMAIN} (HTTP $TUNNEL_APP — check Pangolin resource auth)"
  fi
else
  skip "Tunnel (Newt not running)"
fi

# ─── Database ────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Database${NC}"

USER_COUNT=$(docker compose exec -T v2-postgres psql -U changemaker -d changemaker_v2 -t -c "SELECT COUNT(*) FROM users" 2>/dev/null | tr -d ' ' || echo "0")
if [[ "$USER_COUNT" -gt "0" ]] 2>/dev/null; then
  pass "Users in DB: $USER_COUNT"
else
  fail "No users found in database"
fi

TABLE_COUNT=$(docker compose exec -T v2-postgres psql -U changemaker -d changemaker_v2 -t -c "SELECT COUNT(*) FROM pg_tables WHERE schemaname='public'" 2>/dev/null | tr -d ' ' || echo "0")
if [[ "$TABLE_COUNT" -gt "100" ]] 2>/dev/null; then
  pass "Tables in DB: $TABLE_COUNT"
else
  warn "Table count: $TABLE_COUNT (expected 180+)"
fi

# ─── Summary ─────────────────────────────────────────────────────────────
TOTAL=$((PASS + FAIL + WARN + SKIP))
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [[ "$FAIL" -eq 0 ]]; then
  echo -e "  ${GREEN}${BOLD}ALL TESTS PASSED${NC}  ($PASS passed, $WARN warnings, $SKIP skipped)"
else
  echo -e "  ${RED}${BOLD}$FAIL FAILURES${NC}  ($PASS passed, $FAIL failed, $WARN warnings, $SKIP skipped)"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""

exit "$FAIL"
