#!/usr/bin/env bash
# PR-topic 跨模块告警 (#259 B3)：检查 push 范围跨了多少个顶级模块，超阈值 warn。
#
# 为什么有这个：盘点和 PR #247 复查都显示 "PR 范围混杂跨多 topic" 是反复出现的
# 软规则（5 次 review 提了 5 次没用）。AI Review 在 PR 阶段才提为时已晚，左移
# 到 pre-push 给作者一个"拆 PR 提示"。
#
# 跟 CLAUDE.md「分支生命周期与四道防线 / 一个分支只做一件事」对齐。
#
# 顶级模块识别（启发式，简单粗暴但够用）：
#   backend/src/<segment>/<module>     → be/<segment>/<module>
#   frontend/src/app/<route>           → fe/<route>
#   frontend/src/<top>                 → fe/<top>
#   docs/modules/<module>              → docs/<module>
#   docs/standards / docs/ops          → docs/<area>
#   scripts/<segment>                  → scripts/<segment>
#   .gitea / .agents / .claude / .githooks → 各自单计
#   testing/<segment>                  → testing/<segment>
#
# 阈值默认 4；通过 PR_TOPIC_THRESHOLD 环境变量覆盖。
# 紧急逃生：PR_TOPIC_SKIP=1 跳过（不推荐）。
#
# 用法：bash scripts/ops/check-pr-topic-span.sh [--base origin/develop]

set -euo pipefail

BASE_REF="origin/develop"
while [[ $# -gt 0 ]]; do
  case "$1" in
    --base) BASE_REF="$2"; shift 2 ;;
    -h|--help) sed -n '2,22p' "$0" | sed 's/^# \?//'; exit 0 ;;
    *) echo "未知参数: $1" >&2; exit 2 ;;
  esac
done

if [ -n "${PR_TOPIC_SKIP:-}" ]; then
  exit 0
fi

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

THRESHOLD="${PR_TOPIC_THRESHOLD:-4}"

# 校验 base ref 可达；不可达则 fail-open（不要因为 hook 自身问题阻塞 push）
if ! git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
  exit 0
fi

CHANGED=$(git diff --name-only "${BASE_REF}...HEAD" 2>/dev/null || true)
[ -z "$CHANGED" ] && exit 0

MODULES=$(echo "$CHANGED" | awk -F/ '
  $1 == "backend" && $2 == "src" && NF >= 4   { print "be/" $3 "/" $4; next }
  $1 == "frontend" && $2 == "src" && $3 == "app" && NF >= 5 { print "fe/app/" $4; next }
  $1 == "frontend" && $2 == "src" && NF >= 3  { print "fe/" $3; next }
  $1 == "docs" && $2 == "modules" && NF >= 3  { print "docs/m/" $3; next }
  $1 == "docs" && NF >= 2                     { print "docs/" $2; next }
  $1 == "scripts" && NF >= 2                  { print "scripts/" $2; next }
  $1 == "testing" && NF >= 2                  { print "testing/" $2; next }
  $1 == ".gitea"                              { print ".gitea"; next }
  $1 == ".agents" || $1 == ".claude"          { print ".agents-skills"; next }
  $1 == ".githooks"                           { print ".githooks"; next }
  NF == 1                                     { print "root/" $1; next }
' | sort -u)

COUNT=$(echo "$MODULES" | grep -c . || true)
if [ "$COUNT" -le "$THRESHOLD" ]; then
  exit 0
fi

echo "" >&2
echo "⚠️  PR-topic span: 本次 push 跨 $COUNT 个顶级模块（阈值 $THRESHOLD，可调 PR_TOPIC_THRESHOLD）" >&2
echo "$MODULES" | sed 's/^/  - /' >&2
echo "" >&2
echo "建议：拆成多个 PR，一个 PR 只做一件事（CLAUDE.md「一个分支只做一件事」）" >&2
echo "如本次是合理的跨模块大改（如基础设施升级、契约面统一调整），可在 PR description" >&2
echo "「主要组成」段说明跨度合理性。紧急跳过：PR_TOPIC_SKIP=1" >&2
echo "" >&2
echo "（warn-only，不阻断 push）" >&2
exit 0
