#!/usr/bin/env bash
# Regression test for dashcaddy-post-deploy-patches.sh (the verifier).
# Run from the dashcaddy-api/scripts/ directory:
#   bash test-dashcaddy-post-deploy-verifier.sh
# Exit 0 = all assertions pass, non-zero = failure.
#
# The verifier has FIVE checks:
#   1. server.js exists + uses './src/...' requires (not '../src/...')
#   2. license-manager.js exists in src/managers/ + uses '../../license-keygen'
#   3. src/ directory exists, non-empty, contains src/app.js
#   4. license-keygen.js exists at API root
#   5. src/ require paths — informational warnings only, does not fail build
#
# Test strategy: build synthetic API_DIR trees (clean, broken) and assert the
# right checks pass/fail. No network calls, no real tarballs required.

set -euo pipefail

readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Resolve verifier script — prefer local copy, fall back to canonical /root/dashcaddy/scripts/
VERIFY_SCRIPT="${SCRIPT_DIR}/dashcaddy-post-deploy-patches.sh"
if [[ ! -f "$VERIFY_SCRIPT" ]]; then
  ALT="$(cd "${SCRIPT_DIR}/../../scripts" 2>/dev/null && pwd)/dashcaddy-post-deploy-patches.sh"
  [[ -f "$ALT" ]] && VERIFY_SCRIPT="$ALT"
fi

if [[ ! -f "$VERIFY_SCRIPT" ]]; then
  echo "FAIL: dashcaddy-post-deploy-patches.sh not found (looked in ${SCRIPT_DIR} and ${SCRIPT_DIR}/../../scripts)"
  exit 1
fi

pass=0
fail=0

assert_exit_0() {
  local desc="$1"; shift
  if "$@" >/dev/null 2>&1; then
    echo "  PASS: $desc"
    pass=$(( pass + 1 ))
  else
    echo "  FAIL: $desc — expected exit 0, got $?"
    fail=$(( fail + 1 ))
  fi
}

assert_exit_nonzero() {
  local desc="$1"; shift
  if "$@" >/dev/null 2>&1; then
    echo "  FAIL: $desc — expected non-zero exit, got 0"
    fail=$(( fail + 1 ))
  else
    echo "  PASS: $desc"
    pass=$(( pass + 1 ))
  fi
}

assert_output_contains() {
  local desc="$1" needle="$2"; shift 2
  local output
  output=$("$@" 2>&1 || true)
  if echo "$output" | grep -q "$needle"; then
    echo "  PASS: $desc"
    pass=$(( pass + 1 ))
  else
    echo "  FAIL: $desc — '$needle' not in output:"
    echo "$output" | head -10 | sed 's/^/      /'
    fail=$(( fail + 1 ))
  fi
}

# Build a clean API_DIR tree — all 5 checks should pass.
build_clean_api_dir() {
  local d="$1"
  mkdir -p "$d/src/managers"
  cat > "$d/server.js" << 'EOF'
const { createApp } = require('./src/app');
const platformPaths = require('./platform-paths');
EOF
  cat > "$d/license-keygen.js" << 'EOF'
module.exports = { verifyCode: () => true };
EOF
  cat > "$d/src/app.js" << 'EOF'
module.exports = { createApp: () => ({}) };
EOF
  cat > "$d/src/managers/license-manager.js" << 'EOF'
const keygen = require('../../license-keygen');
module.exports = { load: () => keygen };
EOF
}

# ── Test 1: clean tree — verifier passes 5/5 ─────────────────────────────────
echo "=== Test 1: clean tree (all checks should pass) ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
assert_exit_0 "clean tree passes verifier" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "reports 5/5" "5/5 checks passed" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 2: missing server.js — fails check 1 ────────────────────────────────
echo "=== Test 2: server.js missing → fails ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
rm "$TMP/api/server.js"
assert_exit_nonzero "missing server.js fails build" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "reports server.js failure" "server.js: file missing" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 3: server.js with broken '../src/' requires — fails check 1 ────────
echo "=== Test 3: server.js with '../src/' requires → fails ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
cat > "$TMP/api/server.js" << 'EOF'
const { createApp } = require('../src/app');
EOF
assert_exit_nonzero "broken server.js fails build" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "reports '../src/' breakage" "../src/" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 4: src/ directory missing — fails check 3 (v1.14.4-class bug) ──────
echo "=== Test 4: src/ missing (v1.14.4-class bug) → fails loudly ==="
TMP=$(mktemp -d)
mkdir -p "$TMP/api"
cat > "$TMP/api/server.js" << 'EOF'
const { createApp } = require('./src/app');
EOF
cat > "$TMP/api/license-keygen.js" << 'EOF'
module.exports = {};
EOF
# No src/ at all
assert_exit_nonzero "missing src/ fails build" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "names v1.14.4-class bug" "v1.14.4-class bug" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 5: license-keygen.js missing at root — fails check 4 ───────────────
echo "=== Test 5: license-keygen.js missing at root → fails ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
rm "$TMP/api/license-keygen.js"
assert_exit_nonzero "missing license-keygen.js fails build" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "reports license-keygen.js missing" "license-keygen.js: missing" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 6: license-manager.js with broken './license-keygen' — fails check 2
echo "=== Test 6: license-manager.js uses broken './license-keygen' → fails ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
cat > "$TMP/api/src/managers/license-manager.js" << 'EOF'
const keygen = require('./license-keygen');
module.exports = {};
EOF
assert_exit_nonzero "broken license-manager.js fails build" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "reports broken license-manager path" "broken './license-keygen'" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 7: empty src/ directory — fails check 3 ────────────────────────────
echo "=== Test 7: src/ exists but is empty → fails ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
rm -rf "$TMP/api/src"
mkdir -p "$TMP/api/src"
assert_exit_nonzero "empty src/ fails build" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "reports empty src/" "directory is empty" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 8: src/ exists but missing app.js — fails check 3 ──────────────────
echo "=== Test 8: src/ present but missing app.js → fails ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
rm "$TMP/api/src/app.js"
assert_exit_nonzero "missing src/app.js fails build" bash "$VERIFY_SCRIPT" "$TMP/api"
assert_output_contains "reports missing src/app.js" "src/app.js: missing" bash "$VERIFY_SCRIPT" "$TMP/api"
rm -rf "$TMP"

# ── Test 9: absolute path handling (verify cd doesn't break path resolution) ─
echo "=== Test 9: relative vs absolute API_DIR both work ==="
TMP=$(mktemp -d)
build_clean_api_dir "$TMP/api"
# Run from a DIFFERENT cwd to prove absolute path resolution
(cd /tmp && assert_exit_0 "absolute path works from different cwd" bash "$VERIFY_SCRIPT" "$TMP/api")
rm -rf "$TMP"

# ── Test 10: API_DIR doesn't exist → exits non-zero with clear error ────────
echo "=== Test 10: non-existent API_DIR → fails clearly ==="
assert_exit_nonzero "non-existent API_DIR fails" bash "$VERIFY_SCRIPT" "/tmp/does-not-exist-xyz-12345"

# ── Summary ──────────────────────────────────────────────────────────────────
echo
echo "═══════════════════════════════════════════"
echo "  dashcaddy-post-deploy-patches.sh (verifier) test"
echo "  PASS: $pass    FAIL: $fail"
echo "═══════════════════════════════════════════"

if (( fail > 0 )); then
  exit 1
fi
echo "All tests passed."
