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

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TS_NODE="${ROOT_DIR}/backend/node_modules/.bin/ts-node"

# 显式走 backend 本地 ts-node：npx 在缺依赖时会偷拉全网最新 TS 7 preview，
# 触发 TS5107 (moduleResolution=node10 弃用) 硬错误。
# 第 3 次踩坑：.learnings/ERRORS/ERR-20260418-001.md / ERR-20260429-002.md
require_ts_node() {
  if [ ! -x "$TS_NODE" ]; then
    echo "pre-commit: 未找到 backend/node_modules/.bin/ts-node。" >&2
    echo "  - worktree 也需先 'cd backend && npm install' 才能 commit（hook 校验脚本依赖）。" >&2
    echo "  - 即使 PR 只改 docs/scripts，校验仍需本地 ts-node；不再 fallback 到 npx 拉全网新版。" >&2
    exit 1
  fi
}

# 仅追踪 skill 分发产物（.claude/skills/**），排除 settings.json / settings.local.json
# 等本地 Claude Code 配置——这些文件没有 .agents/ 源头，不走 sync-skills 流程
STAGED_DISTRIBUTION_CHANGES="$(git diff --cached --name-only -- '.claude/skills/**' || true)"
STAGED_SOURCE_CHANGES="$(git diff --cached --name-only -- .agents || true)"
STAGED_CLAUDE_CHANGES="$(git diff --cached --name-only -- CLAUDE.md || true)"
STAGED_AGENTS_CHANGES="$(git diff --cached --name-only -- AGENTS.md || true)"

if [[ -n "${STAGED_DISTRIBUTION_CHANGES}" && -z "${STAGED_SOURCE_CHANGES}" ]]; then
  echo "pre-commit: 检测到 .claude/ 改动，但 .agents/ 未修改。" >&2
  echo "请只在 .agents/skills 中维护内容，然后运行: npm run sync:skills" >&2
  exit 1
fi

if { [[ -n "${STAGED_CLAUDE_CHANGES}" ]] && [[ -z "${STAGED_AGENTS_CHANGES}" ]]; } || \
   { [[ -n "${STAGED_AGENTS_CHANGES}" ]] && [[ -z "${STAGED_CLAUDE_CHANGES}" ]]; }; then
  echo "pre-commit: 检测到入口文档只修改了一份。" >&2
  echo "AGENTS.md 与 CLAUDE.md 采用并行维护模式，请同步更新两份文档后再提交。" >&2
  exit 1
fi

if [[ -n "${STAGED_SOURCE_CHANGES}" ]]; then
  bash "${ROOT_DIR}/scripts/sync-skills.sh"
  git add .agents .claude
fi

bash "${ROOT_DIR}/scripts/check-agent-assets.sh"
bash "${ROOT_DIR}/scripts/check-entry-docs.sh"

# --diff-filter=AM：仅看新增/修改文件，删除/重命名跳过（删了就没 schema 内容可校验）
STAGED_SCHEMA_CHANGES="$(git diff --cached --name-only --diff-filter=AM -- 'backend/prisma/schema/*.prisma' || true)"
if [[ -n "${STAGED_SCHEMA_CHANGES}" ]]; then
  require_ts_node
  (cd "${ROOT_DIR}/backend" && "$TS_NODE" --transpile-only --project "${ROOT_DIR}/testing/scripts/tsconfig.json" "${ROOT_DIR}/testing/scripts/data-scope-fields-check.ts" --staged)
fi

# --diff-filter=AM：删除 service 不需要 access-check（文件已不存在）
STAGED_SERVICE_CHANGES="$(git diff --cached --name-only --diff-filter=AM -- 'backend/src/**/*.service.ts' || true)"
if [[ -n "${STAGED_SERVICE_CHANGES}" ]]; then
  require_ts_node
  (cd "${ROOT_DIR}/backend" && "$TS_NODE" --transpile-only --project "${ROOT_DIR}/testing/scripts/tsconfig.json" "${ROOT_DIR}/testing/scripts/assert-access-check.ts" --staged)
fi

# 审计接入检查：staged 的 controller 含写操作但未声明 @Auditable() 时告警
# 过渡期 warn-only；待团队消化后改为 --mode block
bash "${ROOT_DIR}/scripts/ops/check-controller-auditable.sh" --mode warn

# api-doc-drift 和 migration-count 都需要识别 merge commit 跳过——merge 把上游
# 几十个 commit 的改动一次性 stage 进来，hook 把"staged"当作"本次本地引入"误伤
# 上游已合并的 drift / 多 migration（边界 case）。判定一次复用。
# 用 `git rev-parse --git-dir` 而非 `${ROOT_DIR}/.git/MERGE_HEAD` —— 兼容 worktree
# 场景（worktree 下 .git 是 file 指向真实 git dir）。
GIT_DIR_PATH="$(git rev-parse --git-dir)"
IS_MERGE_COMMIT=false
if [ -f "${GIT_DIR_PATH}/MERGE_HEAD" ] || [ -f "${GIT_DIR_PATH}/MERGE_MSG" ]; then
  IS_MERGE_COMMIT=true
fi

# API 文档漂移检测 (#259 B1)：staged controller 里新增/改 HTTP 装饰器，
# 但 docs/modules/{module}/07-api.md 没对应端点时阻断。
# 2026-05-17 #317 离线评估转正：6 天 55 PR 命中 0，升 block 不会拦合理 PR。
# Merge skip 同 migration-count 同根原因（详见 ERR-20260519-002 / hook 顶部 IS_MERGE_COMMIT）。
if "$IS_MERGE_COMMIT"; then
  echo "pre-commit: merge commit，跳过 API 文档漂移检测"
else
  bash "${ROOT_DIR}/scripts/ops/check-api-doc-drift.sh" --mode block
fi

# 迁移文件数量校验 (#259 B4)：CLAUDE.md 数据库规则"每次提交最多一个迁移文件"
# 把 CI 端 .gitea/workflows/quality-gates.yml migration-file-count 左移到本地
# 默认 block 因为是 CLAUDE.md 明文规则（不是探索期）
# Merge commit 跳过：merge 跨越多 commit 带多个 migration 是合规的（每个 migration
# 在它自己原 commit 里都已经 ≤ 1），hook 把 staged 当一个 commit 算是边界 case。
if "$IS_MERGE_COMMIT"; then
  echo "pre-commit: merge commit，跳过 migration count 检查"
else
  bash "${ROOT_DIR}/scripts/ops/check-migration-count.sh"
fi

# Partial unique 索引守门：禁止删 *_active_key（partial unique）。
# 背景：Prisma PSL 不支持 partial unique → schema 跟 DB 永久 drift →
# `prisma migrate dev` 自动 diff 会主动提议「DROP partial unique」"修复" 回普通 unique，
# 误 accept 后软删除合规悄悄失效。本检查兜底。详见脚本头部注释。
bash "${ROOT_DIR}/scripts/ops/check-partial-unique-guard.sh"

# B2 check-enum-extension 已在 #317 撤下（2026-05-17）：6 天 55 PR 仅 2 命中
# 且全部是新建 type（非扩展），heuristic 区分不了新建 vs 扩展，cry-wolf。
# 脚本保留在 scripts/ops/ 供需要时手动调用。
