#!/usr/bin/env bash
# partial unique guard：禁止 migration 文件删 `*_active_key` partial unique 索引。
#
# 为什么有这个：
#   - 项目里 12 张表（Customer/Supplier/Partner/Location/RobotModel/RobotSku/
#     RobotUnit/PurchaseOrder/SalesOrder/DeliveryRequest/ServiceTicket/PaymentRecord）
#     的 unique 是 DB 层 partial unique `WHERE deleted_at IS NULL`，
#     用于实现"软删 + code 复用"（standard 17 软删除一致）。
#   - 但 Prisma PSL 不能表达 partial unique，schema 里保留普通 @unique 装饰器。
#   - 结果：Prisma schema 跟 DB 永久 drift。每次跑 `prisma migrate dev`，
#     Prisma 会**主动提议**「DROP partial unique → CREATE 普通 unique」"修复" 回 schema 状态。
#   - 如果团队成员不知情、直接 accept 这个提议 → partial unique 退回普通 unique
#     → 软删除合规悄悄失效，且回不去（有真实软删数据后想再加 partial 会冲突）。
#
# 本脚本兜底：扫 staged 新加的 migration.sql，发现 `DROP INDEX .*_active_key`
# 或重建为非 partial unique 的危险 SQL 就 fail，强制人工 review。
#
# 正确改 partial unique 的流程：
#   1. 用 `prisma migrate diff --script` 看 plan
#   2. 手编 migration 文件，去掉自动生成的"重建普通 unique"那段
#   3. 或者真的要改语义（业务上软删后不允许复用），用 --mode warn 跳过本检查
#
# 用法：
#   bash scripts/ops/check-partial-unique-guard.sh                    # block 模式
#   bash scripts/ops/check-partial-unique-guard.sh --mode warn        # 仅警告
#   bash scripts/ops/check-partial-unique-guard.sh --files <a.sql> ...  # 指定文件（CI 用）
#
# 关联：
#   - docs/standards/20-database-review-checklist.md F3 / 原则 17
#   - backend/prisma/migrations/20260517234409_robot_v3_review_fixes/migration.sql 末段

set -euo pipefail

MODE="block"
FILES=()
while [[ $# -gt 0 ]]; do
  case "$1" in
    --mode) MODE="$2"; shift 2 ;;
    --files) shift; while [[ $# -gt 0 && "$1" != --* ]]; do FILES+=("$1"); shift; done ;;
    -h|--help) sed -n '2,30p' "$0" | sed 's/^# \?//'; exit 0 ;;
    *) echo "未知参数: $1" >&2; exit 2 ;;
  esac
done

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

# 默认从 git staged 取（pre-commit 场景）；--files 模式取参数（CI 场景）
if [ ${#FILES[@]} -eq 0 ]; then
  STAGED=$(git diff --cached --name-only --diff-filter=A -- 'backend/prisma/migrations/*/migration.sql' 2>/dev/null || true)
  if [ -z "$STAGED" ]; then
    exit 0
  fi
  while IFS= read -r f; do FILES+=("$f"); done <<< "$STAGED"
fi

VIOLATIONS=()
for f in "${FILES[@]}"; do
  [ -f "$f" ] || continue
  # 危险 pattern A: DROP INDEX *_active_key （直接删 partial unique）
  if grep -nE 'DROP[[:space:]]+(UNIQUE[[:space:]]+)?INDEX[[:space:]]+("?[a-zA-Z0-9_.]+"?\.)?"?[a-zA-Z0-9_]+_active_key"?' "$f" >/dev/null 2>&1; then
    HITS=$(grep -nE 'DROP[[:space:]]+(UNIQUE[[:space:]]+)?INDEX[[:space:]]+("?[a-zA-Z0-9_.]+"?\.)?"?[a-zA-Z0-9_]+_active_key"?' "$f")
    VIOLATIONS+=("$f: 包含 DROP *_active_key（删 partial unique 索引）")
    VIOLATIONS+=("    匹配行：")
    while IFS= read -r line; do VIOLATIONS+=("      $line"); done <<< "$HITS"
  fi
done

if [ ${#VIOLATIONS[@]} -eq 0 ]; then
  exit 0
fi

echo "" >&2
if [ "$MODE" = "warn" ]; then
  echo "⚠️  partial unique guard 警告（--mode warn 不阻断）：" >&2
else
  echo "❌ partial unique guard 违反：禁止删 *_active_key partial unique 索引" >&2
fi
printf '%s\n' "${VIOLATIONS[@]}" >&2
echo "" >&2
echo "背景：这些索引是 standard 17「软删除一致」+ partial unique 的实现，删除会让" >&2
echo "      软删后 code 复用功能悄悄失效。Prisma migrate dev 自动 diff 会主动提议" >&2
echo "      重建普通 unique —— 这正是本检查要拦的反模式。" >&2
echo "" >&2
echo "解决：" >&2
echo "  1. 手编 migration.sql，去掉自动生成的 DROP INDEX *_active_key 段" >&2
echo "  2. 如果真的要改 partial unique 语义（业务决策），手动跑：" >&2
echo "       bash scripts/ops/check-partial-unique-guard.sh --mode warn" >&2
echo "     并在 commit message 里说明业务理由" >&2
echo "  3. 详见 scripts/ops/check-partial-unique-guard.sh 头部注释" >&2

[ "$MODE" = "warn" ] && exit 0 || exit 1
