#!/usr/bin/env bash
set -euo pipefail

PROJECT_DIR="${1:-/home/long/project/蚊子}"
MODE="${2:-preflight}"

failures=()
warnings=()

fail() {
  failures+=("$*")
}

warn() {
  warnings+=("$*")
}

require_file() {
  local file="$1"
  local hint="$2"
  if [ ! -f "$file" ]; then
    fail "缺少文件: $file（$hint）"
  fi
}

require_contains() {
  local file="$1"
  local regex="$2"
  local hint="$3"
  if ! grep -Eq "$regex" "$file"; then
    fail "文件契约不满足: $file（$hint）"
  fi
}

require_non_empty_kv() {
  local file="$1"
  local key="$2"
  local hint="$3"
  local line
  line="$(grep -E "^${key}=" "$file" | tail -n1 || true)"
  if [ -z "$line" ]; then
    fail "缺少配置项: ${key}（$hint）"
    return
  fi
  local value="${line#*=}"
  if [ -z "${value// /}" ]; then
    fail "配置项为空: ${key}（$hint）"
  fi
}

E2E_PROPS="$PROJECT_DIR/src/main/resources/application-e2e.properties"
TEST_PROPS="$PROJECT_DIR/src/test/resources/application.properties"
TEST_YML="$PROJECT_DIR/src/main/resources/application-test.yml"
MIGRATION_DIR="$PROJECT_DIR/src/main/resources/db/migration"
STATE_DIR="$PROJECT_DIR/logs/e2e-automation"

require_file "$E2E_PROPS" "E2E环境配置"
require_file "$TEST_PROPS" "测试资源配置"
require_file "$TEST_YML" "test profile配置"
require_file "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" "权限seed必须存在"
require_file "$MIGRATION_DIR/V37__Seed_user_roles.sql" "用户角色seed必须存在"

if [ -f "$E2E_PROPS" ]; then
  require_contains "$E2E_PROPS" '^spring\.datasource\.url=jdbc:h2:mem:' 'E2E必须使用内存库，避免污染真实环境'
  require_contains "$E2E_PROPS" '^spring\.flyway\.enabled=false' 'E2E依赖JPA自动建表时需关闭Flyway'
  require_contains "$E2E_PROPS" '^mosquito\.security\.csrf\.enabled=false' 'E2E接口测试需要关闭CSRF'
  require_contains "$E2E_PROPS" '^mosquito\.callback\.allow-localhost=true' 'E2E回调需允许localhost'
  require_non_empty_kv "$E2E_PROPS" 'mosquito.security.jwt.secret' '鉴权token签名密钥必填'
fi

if [ -f "$TEST_PROPS" ]; then
  require_contains "$TEST_PROPS" '^spring\.datasource\.url=jdbc:h2:mem:' '单测必须使用H2内存库'
  require_contains "$TEST_PROPS" '^spring\.jpa\.hibernate\.ddl-auto=create-drop' '测试环境要求自动建删表'
fi

if [ -f "$MIGRATION_DIR/V37__Seed_user_roles.sql" ]; then
  require_contains "$MIGRATION_DIR/V37__Seed_user_roles.sql" 'INSERT INTO sys_user_role' '必须初始化用户角色关联，避免鉴权假绿'
fi

if [ -f "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" ]; then
  require_contains "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" 'INSERT INTO sys_role ' '必须初始化角色数据'
  require_contains "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" 'INSERT INTO sys_permission ' '必须初始化权限数据'
fi

if [ -n "${SPRING_PROFILES_ACTIVE:-}" ]; then
  if echo "$SPRING_PROFILES_ACTIVE" | grep -Eqi '(^|,)(prod|production)(,|$)'; then
    fail "检测到危险profile: SPRING_PROFILES_ACTIVE=$SPRING_PROFILES_ACTIVE（禁止在测试链路使用prod）"
  fi
else
  warn "未设置 SPRING_PROFILES_ACTIVE（建议runner显式设为e2e）"
fi

CLAUDE_BIN_DEFAULT="$HOME/.cursor/extensions/anthropic.claude-code-2.1.15-linux-x64/resources/native-binary/claude"
CLAUDE_BIN_EFFECTIVE="${CLAUDE_BIN:-$CLAUDE_BIN_DEFAULT}"
if [ "$MODE" = "runner" ]; then
  if [ ! -x "$CLAUDE_BIN_EFFECTIVE" ]; then
    fail "CLAUDE_BIN不可执行: $CLAUDE_BIN_EFFECTIVE（runner无法产出报告）"
  fi
fi

mkdir -p "$STATE_DIR" 2>/dev/null || fail "无法创建状态目录: $STATE_DIR"
if [ ! -w "$STATE_DIR" ]; then
  fail "状态目录不可写: $STATE_DIR"
fi

# ============================================================
# E2E严格断言检查（MOSQ-P1-001）
# 检查 user-journey*.spec.ts 是否存在宽松断言模式
# ============================================================
E2E_TEST_DIR="$PROJECT_DIR/frontend/e2e/tests"
check_e2e_strict_assertions() {
  local spec_files=("$E2E_TEST_DIR"/user-journey*.spec.ts)
  local found_issues=0

  for spec_file in "${spec_files[@]}"; do
    if [ ! -f "$spec_file" ]; then
      continue
    fi

    # 检查是否存在宽松断言：expect([200, 401, 403]) 这种模式
    # 严格模式应该是：expect(status).toBeGreaterThanOrEqual(200) 或类似
    if grep -q 'expect(\[200, 401' "$spec_file" 2>/dev/null; then
      fail "E2E严格断言违规: $spec_file 包含宽松断言 expect([200, 401, 403])"
      found_issues=$((found_issues + 1))
    fi

    if grep -q 'expect(\[200, 201, 401' "$spec_file" 2>/dev/null; then
      fail "E2E严格断言违规: $spec_file 包含宽松断言 expect([200, 201, 401, 403])"
      found_issues=$((found_issues + 1))
    fi

    # 检查是否存在 hasRealApiCredentials 函数调用
    if ! grep -q 'hasRealApiCredentials' "$spec_file" 2>/dev/null; then
      warn "E2E建议: $spec_file 未使用 hasRealApiCredentials 函数"
    fi

    # 检查是否存在 test.skip 保护
    if ! grep -q 'test\.skip' "$spec_file" 2>/dev/null; then
      warn "E2E建议: $spec_file 未使用 test.skip 进行条件跳过"
    fi
  done

  return $found_issues
}

if [ -d "$E2E_TEST_DIR" ]; then
  check_e2e_strict_assertions || true
fi

if [ ${#warnings[@]} -gt 0 ]; then
  for w in "${warnings[@]}"; do
    echo "[WARN] $w"
  done
fi

if [ ${#failures[@]} -gt 0 ]; then
  echo "[DATA-CONTRACT] FAIL (${#failures[@]}项)"
  for f in "${failures[@]}"; do
    echo " - $f"
  done
  exit 2
fi

echo "[DATA-CONTRACT] PASS mode=$MODE"
