#!/usr/bin/env bash
#
# 扫描 staged 的 controller 文件，检查写操作（POST/PUT/PATCH/DELETE）是否标注
# @Auditable()。审计模块是契约面（参见 docs/modules/audit-system/01-prd.md），
# 凡是改变业务数据的端点都应该入审计。
#
# 模式：
#   warn  - 仅打印警告，不阻断 commit（默认，过渡期使用）
#   block - 阻断 commit
#
# 用法：
#   bash scripts/ops/check-controller-auditable.sh [--mode warn|block] [--all]
#     --all 扫描全部 controller 而不限于 staged（用于 CI / 全量审计）
#
# 退出码：
#   0 - 通过 / warn 模式下总是 0
#   1 - block 模式下发现违规

set -uo pipefail

MODE="warn"
SCOPE="staged"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --mode)
      MODE="${2:-warn}"
      shift 2
      ;;
    --all)
      SCOPE="all"
      shift
      ;;
    *)
      echo "未知参数: $1" >&2
      exit 2
      ;;
  esac
done

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

if [[ "${SCOPE}" == "staged" ]]; then
  FILES=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null \
    | grep -E '^backend/src/.*\.controller\.ts$' || true)
else
  FILES=$(find backend/src -type f -name '*.controller.ts' 2>/dev/null || true)
fi

[[ -z "${FILES}" ]] && exit 0

VIOLATIONS=()

while IFS= read -r f; do
  [[ -z "$f" ]] && continue
  [[ ! -f "$f" ]] && continue

  # 该文件是否定义了写操作（POST/PUT/PATCH/DELETE 装饰器）
  if ! grep -qE '^[[:space:]]*@(Post|Put|Patch|Delete)\(' "$f"; then
    continue
  fi

  # 同一个方法装饰器组里是否有 @Auditable
  # 简化策略：只要文件里有 @Auditable 就认为有意识接入审计；进一步精细的方法级
  # 检查留给后续 ts-morph 版本。
  if grep -qE '@Auditable\(' "$f"; then
    continue
  fi

  # 排除审计模块自身、健康检查等元控制器
  case "$f" in
    backend/src/core/observability/audit/*) continue ;;
    backend/src/core/observability/logging/*) continue ;;
    *health.controller.ts|*health-check*) continue ;;
  esac

  VIOLATIONS+=("$f")
done <<< "${FILES}"

[[ ${#VIOLATIONS[@]} -eq 0 ]] && exit 0

echo "" >&2
echo "==== 审计接入检查 ====" >&2
echo "以下 controller 含写操作（POST/PUT/PATCH/DELETE）但未声明 @Auditable()：" >&2
for v in "${VIOLATIONS[@]}"; do
  echo "  - $v" >&2
done
echo "" >&2
echo "审计模块要求所有改变业务数据的端点入审计。请：" >&2
echo "  1. 在写操作方法上加 @Auditable() 装饰器" >&2
echo "  2. 敏感操作（密码/权限/删除）加 @Sensitive()" >&2
echo "  3. 财务操作（支付/退款）加 @Financial()" >&2
echo "  详见 docs/modules/audit-system/README.md「快速开始」段" >&2
echo "" >&2

if [[ "${MODE}" == "block" ]]; then
  exit 1
fi

echo "（当前为 warn 模式，未阻断 commit；如需阻断改 .githooks/pre-commit 调用为 --mode block）" >&2
exit 0
