#!/usr/bin/env bash
# Azaion UI — performance test runner.
#
# Generated by .cursor/skills/test-spec phase 4. Implements the NFT-PERF-* scenarios
# from _docs/02_document/tests/performance-tests.md. Thresholds are sourced from
# _docs/00_problem/input_data/expected_results/results_report.md (rows 11, 40, 98 + AC-11 + AC-23).
#
# Most NFT-PERF-* tests are observable browser timings, not server load tests. The
# script therefore runs Playwright-based measurements rather than k6/locust.
#
# Profile mapping (per environment.md → Test Execution):
#   - NFT-PERF-01 (bundle ≤ 2 MB gzip)            : static — checks dist/ on host
#   - NFT-PERF-02..09                              : fast or e2e — Playwright
#   - NFT-PERF-10 (FCP ≤ 3 000 ms on /flights)    : e2e — Playwright against the suite stack
#
# Usage:
#   scripts/run-performance-tests.sh                # run all NFT-PERF-* (skips quarantined)
#   scripts/run-performance-tests.sh --static-only  # only NFT-PERF-01 (bundle size)
#   scripts/run-performance-tests.sh --e2e-only     # only NFT-PERF-* that require the stack
#   scripts/run-performance-tests.sh --bundle-max-bytes 2097152  # override bundle threshold

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
SUITE_ROOT="$(cd "$PROJECT_ROOT/.." && pwd)"
RESULTS_DIR="$PROJECT_ROOT/test-output"

RUN_STATIC=true
RUN_E2E=true

# Thresholds (defaults from results_report.md; overridable via flags).
BUNDLE_MAX_BYTES=$((2 * 1024 * 1024))   # AC-11 / NFT-PERF-01 (row 40): 2 MB gzipped initial JS
FCP_MAX_MS=3000                          # NFT-PERF-10 (row 98): warm-cache FCP on /flights, edge profile
AUTH_REFRESH_MAX_MS=200                  # NFT-PERF-02 (row 11): refresh round-trip target

for arg in "$@"; do
  case "$arg" in
    --static-only)              RUN_STATIC=true;  RUN_E2E=false ;;
    --e2e-only)                 RUN_STATIC=false; RUN_E2E=true  ;;
    --bundle-max-bytes=*)       BUNDLE_MAX_BYTES="${arg#*=}" ;;
    --bundle-max-bytes)         shift; BUNDLE_MAX_BYTES="${1:-$BUNDLE_MAX_BYTES}" ;;
    --fcp-max-ms=*)             FCP_MAX_MS="${arg#*=}" ;;
    --fcp-max-ms)               shift; FCP_MAX_MS="${1:-$FCP_MAX_MS}" ;;
    --auth-refresh-max-ms=*)    AUTH_REFRESH_MAX_MS="${arg#*=}" ;;
    --auth-refresh-max-ms)      shift; AUTH_REFRESH_MAX_MS="${1:-$AUTH_REFRESH_MAX_MS}" ;;
    -h|--help)
      sed -n '2,22p' "$0" | sed 's/^# \{0,1\}//'
      exit 0
      ;;
    *)
      echo "Unknown argument: $arg" >&2
      exit 2
      ;;
  esac
done

E2E_COMPOSE_STARTED_HERE=false

cleanup() {
  if [ "$E2E_COMPOSE_STARTED_HERE" = "true" ]; then
    docker compose -f "$PROJECT_ROOT/e2e/docker-compose.suite-e2e.yml" down -v --remove-orphans || true
  fi
}
trap cleanup EXIT

mkdir -p "$RESULTS_DIR"

cd "$PROJECT_ROOT"

echo "[run-performance-tests] thresholds:"
echo "  bundle (NFT-PERF-01)     : ≤ $BUNDLE_MAX_BYTES bytes gzipped"
echo "  FCP    (NFT-PERF-10)     : ≤ $FCP_MAX_MS ms"
echo "  auth refresh (NFT-PERF-02): ≤ $AUTH_REFRESH_MAX_MS ms"
echo "  static : $RUN_STATIC"
echo "  e2e    : $RUN_E2E"

# ----------------------------------------------------------------------------
# Install deps (matches run-tests.sh).
# ----------------------------------------------------------------------------
if ! command -v bun >/dev/null 2>&1; then
  echo "[run-performance-tests] FATAL: bun is required (project pins bun@1.3.11)." >&2
  exit 1
fi
echo "[run-performance-tests] installing dependencies..."
if [ -f "$PROJECT_ROOT/bun.lock" ] || [ -f "$PROJECT_ROOT/bun.lockb" ]; then
  bun install --frozen-lockfile
else
  bun install
fi

OVERALL_EXIT=0
SUMMARY_FILE="$RESULTS_DIR/performance-summary.txt"
: > "$SUMMARY_FILE"

record() {
  # $1 = scenario id, $2 = result (PASS|FAIL|SKIP|QUARANTINE), $3 = measured, $4 = threshold
  printf '%-14s %-12s measured=%-14s threshold=%s\n' "$1" "$2" "$3" "$4" | tee -a "$SUMMARY_FILE"
}

# ----------------------------------------------------------------------------
# Static perf scenarios.
# ----------------------------------------------------------------------------
if [ "$RUN_STATIC" = "true" ]; then
  echo "[run-performance-tests] === NFT-PERF-01 (bundle size) ==="
  if [ ! -d "$PROJECT_ROOT/dist" ]; then
    echo "[NFT-PERF-01] dist/ not present — running 'bun run build'..."
    bun run build
  fi

  # Sum gzipped sizes of dist/assets/*.js (the initial JS bundle is index-*.js per Vite).
  BUNDLE_BYTES=$(
    find "$PROJECT_ROOT/dist/assets" -maxdepth 1 -name '*.js' -print0 2>/dev/null \
    | xargs -0 -I{} sh -c 'gzip -c "{}" | wc -c' \
    | awk '{ s += $1 } END { print (s ? s : 0) }'
  )
  echo "[NFT-PERF-01] gzipped dist/assets/*.js = $BUNDLE_BYTES bytes"
  if [ "$BUNDLE_BYTES" -le "$BUNDLE_MAX_BYTES" ]; then
    record "NFT-PERF-01" "PASS" "${BUNDLE_BYTES}B" "≤ ${BUNDLE_MAX_BYTES}B"
  else
    record "NFT-PERF-01" "FAIL" "${BUNDLE_BYTES}B" "≤ ${BUNDLE_MAX_BYTES}B"
    OVERALL_EXIT=1
  fi
fi

# ----------------------------------------------------------------------------
# E2E perf scenarios (Playwright-based).
# The Playwright project lands at autodev Step 5 (Decompose Tests). Until it
# ships, NFT-PERF-02..10 are SKIPPED (not FAILED) so this script can run on
# the spec-only baseline without producing false negatives.
# ----------------------------------------------------------------------------
if [ "$RUN_E2E" = "true" ]; then
  COMPOSE_FILE="$PROJECT_ROOT/e2e/docker-compose.suite-e2e.yml"
  PERF_PROJECT="$PROJECT_ROOT/e2e/playwright.perf.config.ts"

  if [ ! -f "$PERF_PROJECT" ]; then
    echo "[run-performance-tests] Playwright perf project ($PERF_PROJECT) not yet wired."
    echo "[run-performance-tests] Awaiting NFT-PERF-* task implementations (AZ-457..AZ-482); until then the e2e perf scenarios are SKIPPED."
    for id in NFT-PERF-02 NFT-PERF-03 NFT-PERF-04 NFT-PERF-05 NFT-PERF-06 NFT-PERF-07 NFT-PERF-08 NFT-PERF-09 NFT-PERF-10; do
      record "$id" "SKIP" "n/a" "deferred to per-AC test tasks"
    done
  elif [ ! -f "$COMPOSE_FILE" ]; then
    echo "[run-performance-tests] FATAL: $COMPOSE_FILE not found." >&2
    OVERALL_EXIT=1
  elif ! command -v docker >/dev/null 2>&1; then
    echo "[run-performance-tests] FATAL: docker is required for the e2e perf profile." >&2
    OVERALL_EXIT=1
  else
    echo "[run-performance-tests] starting compose stack..."
    docker compose -f "$COMPOSE_FILE" up -d --build
    E2E_COMPOSE_STARTED_HERE=true

    echo "[run-performance-tests] running Playwright perf project..."
    if FCP_MAX_MS="$FCP_MAX_MS" AUTH_REFRESH_MAX_MS="$AUTH_REFRESH_MAX_MS" \
       bunx playwright test --config "$PERF_PROJECT" 2>&1 | tee "$RESULTS_DIR/perf-playwright.txt"; then
      echo "[run-performance-tests] Playwright perf PASSED"
    else
      echo "[run-performance-tests] Playwright perf FAILED — see $RESULTS_DIR/perf-playwright.txt"
      OVERALL_EXIT=1
    fi
  fi
fi

# Quarantined scenarios (documentary only — never gate today).
record "NFT-PERF-03" "QUARANTINE" "—" "Step 8 hardening (SSE refresh rotation)"
record "NFT-PERF-08" "QUARANTINE" "—" "Step 4 fix (panel-width persistence)"
record "NFT-PERF-09" "QUARANTINE" "—" "Step 4 fix (settings save error surfacing)"

echo ""
echo "[run-performance-tests] summary written to $SUMMARY_FILE"
echo "[run-performance-tests] exit code: $OVERALL_EXIT"

exit "$OVERALL_EXIT"
