#!/usr/bin/env bash
# 端到端回归测试:走完整 next-auth OTP 登录 → /api/me → /api/vote 4 种路径
#
# 测试用户:全新手机号 13800138000(测试结束 cleanup-test-user.mjs 删除)
# dev OTP 万能码:123456
# 实际命中 route handler,不绕过任何中间件。

set -uo pipefail

BASE="http://localhost:3000"
PHONE="13800138000"
CODE="123456"
COOKIES=$(mktemp)
trap 'rm -f "$COOKIES"' EXIT

green() { echo -e "\033[32m$1\033[0m"; }
red()   { echo -e "\033[31m$1\033[0m"; }
yel()   { echo -e "\033[33m$1\033[0m"; }

# 累计通过 / 失败
PASS=0
FAIL=0
assert_eq() {
  local name="$1" expected="$2" actual="$3"
  if [[ "$actual" == "$expected" ]]; then
    PASS=$((PASS+1)); green "  [PASS] $name"
  else
    FAIL=$((FAIL+1)); red "  [FAIL] $name -- expected=$expected actual=$actual"
  fi
}
assert_contains() {
  local name="$1" needle="$2" haystack="$3"
  if echo "$haystack" | grep -q "$needle"; then
    PASS=$((PASS+1)); green "  [PASS] $name"
  else
    FAIL=$((FAIL+1)); red "  [FAIL] $name -- did not find '$needle' in: $haystack"
  fi
}

echo "=== 端到端回归测试 ==="
echo "测试用户 phone=$PHONE"
echo ""

# ===== 0. cleanup 任何上次残留的测试数据(测试幂等) =====
yel "[0] cleanup 上次测试残留"
node scripts/cleanup-test-user.mjs "$PHONE" 2>&1 | sed 's/^/  /'

# ===== 1. 取 CSRF token =====
yel "[1] 获取 CSRF token"
CSRF_RAW=$(curl -s -c "$COOKIES" "$BASE/api/auth/csrf")
CSRF=$(echo "$CSRF_RAW" | sed -n 's/.*"csrfToken":"\([^"]*\)".*/\1/p')
if [[ -z "$CSRF" ]]; then
  red "无法获取 csrfToken,响应:$CSRF_RAW"
  exit 1
fi
green "  csrfToken=${CSRF:0:20}..."

# ===== 2. OTP 登录(Credentials provider 路径 /api/auth/callback/phone-otp) =====
yel "[2] OTP 登录 phone=$PHONE code=$CODE"
LOGIN_HTTP=$(curl -s -b "$COOKIES" -c "$COOKIES" -o /tmp/login.body -w "%{http_code}" \
  -X POST "$BASE/api/auth/callback/phone-otp" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "phone=$PHONE" \
  --data-urlencode "code=$CODE" \
  --data-urlencode "csrfToken=$CSRF" \
  --data-urlencode "redirect=false" \
  --data-urlencode "json=true")
echo "  HTTP $LOGIN_HTTP"

# ===== 3. 验证 session 已建立 =====
yel "[3] 验证 session"
SESSION=$(curl -s -b "$COOKIES" "$BASE/api/auth/session")
echo "  session: $SESSION"
assert_contains "session 包含 user.id" '"id"' "$SESSION"

# ===== 4. GET /api/me 验返回结构 =====
yel "[4] GET /api/me 验证新字段"
ME=$(curl -s -b "$COOKIES" "$BASE/api/me")
echo "  body 摘要: $(echo "$ME" | head -c 300)..."
assert_contains "/api/me 返回 ok:true"          '"ok":true'           "$ME"
assert_contains "/api/me 含 voteQuota 字段"     '"voteQuota"'         "$ME"
assert_contains "/api/me voteQuota.total=12"   '"total":12'           "$ME"
assert_contains "/api/me 含 votedArtists 字段" '"votedArtists"'      "$ME"
if echo "$ME" | grep -q '"dailyQuota"'; then
  FAIL=$((FAIL+1)); red "  [FAIL] /api/me 仍含 dailyQuota 字段(应已被 voteQuota 替换)"
else
  PASS=$((PASS+1)); green "  [PASS] /api/me 不再含旧 dailyQuota 字段"
fi

# ===== 5. POST /api/vote 投未投过的艺人(预期成功) =====
TEST_ARTIST="001"
yel "[5] POST /api/vote artistId=$TEST_ARTIST(首次投,预期 200)"
V1=$(curl -s -b "$COOKIES" -X POST "$BASE/api/vote" \
  -H "Content-Type: application/json" \
  -d "{\"artistId\":\"$TEST_ARTIST\"}")
echo "  body: $V1"
assert_contains "首投返回 ok:true"          '"ok":true'      "$V1"
assert_contains "首投返回 totalQuota:12"    '"totalQuota":12' "$V1"
assert_contains "首投返回 votedCount=1"     '"votedCount":1'  "$V1"
assert_contains "首投返回 remaining=11"     '"remaining":11'  "$V1"

# ===== 6. POST /api/vote 同一艺人(预期 409 ALREADY_VOTED) =====
yel "[6] POST /api/vote artistId=$TEST_ARTIST(重投,预期 409 ALREADY_VOTED)"
V2=$(curl -s -b "$COOKIES" -X POST "$BASE/api/vote" \
  -H "Content-Type: application/json" \
  -d "{\"artistId\":\"$TEST_ARTIST\"}")
echo "  body: $V2"
assert_contains "重投返回 ok:false"          '"ok":false'           "$V2"
assert_contains "重投返回 ALREADY_VOTED"     '"code":"ALREADY_VOTED"' "$V2"

# ===== 7. POST /api/vote 不存在的艺人(预期 404 NOT_FOUND) =====
yel "[7] POST /api/vote artistId=999(不存在,预期 404)"
V3=$(curl -s -b "$COOKIES" -X POST "$BASE/api/vote" \
  -H "Content-Type: application/json" \
  -d '{"artistId":"999"}')
echo "  body: $V3"
assert_contains "无效艺人返回 ok:false"      '"ok":false'        "$V3"
assert_contains "无效艺人返回 NOT_FOUND"     '"code":"NOT_FOUND"' "$V3"

# ===== 8. 再次 GET /api/me 验 votedArtists 含新投艺人 =====
yel "[8] GET /api/me 复查 votedArtists"
ME2=$(curl -s -b "$COOKIES" "$BASE/api/me")
assert_contains "复查 votedArtists 含 $TEST_ARTIST" "\"$TEST_ARTIST\"" "$ME2"
assert_contains "复查 voteQuota.used=1"      '"used":1'     "$ME2"
assert_contains "复查 voteQuota.remaining=11" '"remaining":11' "$ME2"

# ===== 9. 验证未登录 → 401 =====
yel "[9] 未登录调 /api/vote(预期 401)"
V_NOAUTH=$(curl -s -X POST "$BASE/api/vote" \
  -H "Content-Type: application/json" \
  -d '{"artistId":"001"}')
assert_contains "无 session 返回 UNAUTHORIZED" '"code":"UNAUTHORIZED"' "$V_NOAUTH"

# ===== 10. 最终 cleanup =====
yel "[10] 测试结束 cleanup"
node scripts/cleanup-test-user.mjs "$PHONE" 2>&1 | sed 's/^/  /'

# ===== 汇总 =====
echo ""
echo "=== 汇总 ==="
echo "通过 $PASS · 失败 $FAIL"
if [[ $FAIL -gt 0 ]]; then
  red "回归测试有失败,详见上方"
  exit 1
else
  green "全部通过"
fi
