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

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"

# shellcheck source=../../scripts/lib/pg-bootstrap.sh
source "${ROOT_DIR}/scripts/lib/pg-bootstrap.sh"

load_backend_env() {
  local env_file="${ROOT_DIR}/backend/.env"
  if [[ -f "${env_file}" ]]; then
    set -a
    # shellcheck disable=SC1090
    source "${env_file}"
    set +a
  fi
}

setup_test_db_env() {
  load_backend_env

  export TEST_DB_CONTAINER_NAME="${TEST_DB_CONTAINER_NAME:-ffoa-test-postgres}"
  export TEST_DB_PORT="${TEST_DB_PORT:-35432}"
  export TEST_DB_NAME="${TEST_DB_NAME:-ffws_integration_test}"
  export TEST_DB_USER="${TEST_DB_USER:-ffws_test}"
  export TEST_DB_PASSWORD="${TEST_DB_PASSWORD:-ffws_test_password}"
  export TEST_DATABASE_URL="${TEST_DATABASE_URL:-postgresql://${TEST_DB_USER}:${TEST_DB_PASSWORD}@127.0.0.1:${TEST_DB_PORT}/${TEST_DB_NAME}}"
  export NODE_ENV="test"
  export ALLOW_TEST_DB_CLEANUP="true"
  export DATABASE_URL="${TEST_DATABASE_URL}"
  # 集成测试要反复登录管理员，把限流放开
  export AUTH_THROTTLER_TTL_MS="${AUTH_THROTTLER_TTL_MS:-1000}"
  export AUTH_THROTTLER_LIMIT="${AUTH_THROTTLER_LIMIT:-10000}"

  # 测试用 Redis（与本地 dev 的 4103 完全隔离，避免污染开发缓存/Token 黑名单）
  # 强制覆盖 backend/.env 中的 REDIS_*，IAM 对 Redis 是硬依赖（fail secure，不可降级）
  export TEST_REDIS_CONTAINER_NAME="${TEST_REDIS_CONTAINER_NAME:-ffoa-test-redis}"
  export TEST_REDIS_PORT="${TEST_REDIS_PORT:-36379}"
  export REDIS_HOST="127.0.0.1"
  export REDIS_PORT="${TEST_REDIS_PORT}"
  export REDIS_PASSWORD=""
  export REDIS_DB="0"
  export REDIS_KEY_PREFIX="ffws_test:"
}

wait_for_test_db() {
  PG_BOOTSTRAP_LOG_PREFIX="test-db" \
    wait_for_pg_container "${TEST_DB_CONTAINER_NAME}" "${TEST_DB_USER}" "${TEST_DB_NAME}" 30
}

ensure_test_db() {
  setup_test_db_env

  if ! command -v docker >/dev/null 2>&1; then
    echo "test-db: 未找到 docker，请先安装 Docker。" >&2
    exit 1
  fi

  if docker ps -a --format '{{.Names}}' | grep -Fxq "${TEST_DB_CONTAINER_NAME}"; then
    if ! docker ps --format '{{.Names}}' | grep -Fxq "${TEST_DB_CONTAINER_NAME}"; then
      echo "test-db: 启动已有测试数据库容器 ${TEST_DB_CONTAINER_NAME}"
      docker start "${TEST_DB_CONTAINER_NAME}" >/dev/null
    else
      echo "test-db: 复用已有测试数据库容器 ${TEST_DB_CONTAINER_NAME}"
    fi
  else
    echo "test-db: 创建测试数据库容器 ${TEST_DB_CONTAINER_NAME}"
    docker run -d \
      --name "${TEST_DB_CONTAINER_NAME}" \
      -e POSTGRES_DB="${TEST_DB_NAME}" \
      -e POSTGRES_USER="${TEST_DB_USER}" \
      -e POSTGRES_PASSWORD="${TEST_DB_PASSWORD}" \
      -p "${TEST_DB_PORT}:5432" \
      postgres:16-alpine >/dev/null
  fi

  wait_for_test_db
}

wait_for_test_redis() {
  local retries=30
  local attempt=1

  while (( attempt <= retries )); do
    if docker exec "${TEST_REDIS_CONTAINER_NAME}" redis-cli ping 2>/dev/null | grep -q PONG; then
      echo "test-redis: Redis 已就绪 (${TEST_REDIS_CONTAINER_NAME}:${TEST_REDIS_PORT})"
      return 0
    fi
    sleep 1
    attempt=$((attempt + 1))
  done

  echo "test-redis: Redis 启动超时" >&2
  return 1
}

ensure_test_redis() {
  setup_test_db_env

  if ! command -v docker >/dev/null 2>&1; then
    echo "test-redis: 未找到 docker，请先安装 Docker。" >&2
    exit 1
  fi

  if docker ps -a --format '{{.Names}}' | grep -Fxq "${TEST_REDIS_CONTAINER_NAME}"; then
    if ! docker ps --format '{{.Names}}' | grep -Fxq "${TEST_REDIS_CONTAINER_NAME}"; then
      echo "test-redis: 启动已有测试 Redis 容器 ${TEST_REDIS_CONTAINER_NAME}"
      docker start "${TEST_REDIS_CONTAINER_NAME}" >/dev/null
    else
      echo "test-redis: 复用已有测试 Redis 容器 ${TEST_REDIS_CONTAINER_NAME}"
    fi
  else
    echo "test-redis: 创建测试 Redis 容器 ${TEST_REDIS_CONTAINER_NAME}"
    docker run -d \
      --name "${TEST_REDIS_CONTAINER_NAME}" \
      -p "${TEST_REDIS_PORT}:6379" \
      redis:7-alpine >/dev/null
  fi

  wait_for_test_redis
}

reset_test_db_schema() {
  setup_test_db_env

  echo "test-db: 删除并重建测试库，确保干净状态"
  # ⚠️ 不要再把 DROP/CREATE 用 `>/dev/null 2>&1` 吞错。
  # 若 DROP 因连接未终止失败、CREATE 因 DB 已存在失败，下游 db push 会跑在
  # 旧数据上 → seed 被覆盖 / 索引不一致，全 run 大面积 403/FK。
  docker exec "${TEST_DB_CONTAINER_NAME}" psql -U "${TEST_DB_USER}" -d postgres -v ON_ERROR_STOP=1 \
    -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='${TEST_DB_NAME}' AND pid<>pg_backend_pid();" >/dev/null
  docker exec "${TEST_DB_CONTAINER_NAME}" psql -U "${TEST_DB_USER}" -d postgres -v ON_ERROR_STOP=1 \
    -c "DROP DATABASE IF EXISTS ${TEST_DB_NAME};"
  docker exec "${TEST_DB_CONTAINER_NAME}" psql -U "${TEST_DB_USER}" -d postgres -v ON_ERROR_STOP=1 \
    -c "CREATE DATABASE ${TEST_DB_NAME};"
  echo "test-db: 数据库已重建"

  # squash 后（issue #213）baseline 迁移自带 CREATE EXTENSION citext，
  # 不再需要在脚本里手动建扩展；改用 migrate deploy 走标准迁移路径。
  echo "test-db: 应用迁移并初始化种子数据"
  (
    cd "${ROOT_DIR}/backend"
    DATABASE_URL="${TEST_DATABASE_URL}" node_modules/.bin/prisma migrate deploy >/dev/null
    DATABASE_URL="${TEST_DATABASE_URL}" node_modules/.bin/ts-node prisma/seed.ts >/dev/null
  )
}

stop_test_db() {
  setup_test_db_env

  if docker ps -a --format '{{.Names}}' | grep -Fxq "${TEST_DB_CONTAINER_NAME}"; then
    echo "test-db: 停止并删除测试数据库容器 ${TEST_DB_CONTAINER_NAME}"
    docker rm -f "${TEST_DB_CONTAINER_NAME}" >/dev/null
  else
    echo "test-db: 测试数据库容器不存在，无需清理"
  fi

  if docker ps -a --format '{{.Names}}' | grep -Fxq "${TEST_REDIS_CONTAINER_NAME}"; then
    echo "test-redis: 停止并删除测试 Redis 容器 ${TEST_REDIS_CONTAINER_NAME}"
    docker rm -f "${TEST_REDIS_CONTAINER_NAME}" >/dev/null
  else
    echo "test-redis: 测试 Redis 容器不存在，无需清理"
  fi
}
