#!/bin/bash
# 权限码一致性校验脚本
# 校验后端/数据库/前端/canonical基线四维权限码差异
# 支持多段权限码（如 approval.index.batch.transfer.ALL）和连字符（如 system.api-key.create.ALL）

set -e

echo "=== 权限码一致性校验 ==="

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"

BACKEND_PERMS="$SCRIPT_DIR/.permission_check_backend.txt"
FRONTEND_PERMS="$SCRIPT_DIR/.permission_check_frontend.txt"
DB_PERMS="$SCRIPT_DIR/.permission_check_db.txt"
CANONICAL_PERMS="$SCRIPT_DIR/.permission_check_canonical.txt"
DIFF_REPORT="$SCRIPT_DIR/permission_diff_report.md"

# 清理旧文件
rm -f "$BACKEND_PERMS" "$FRONTEND_PERMS" "$DB_PERMS" "$CANONICAL_PERMS" "$DIFF_REPORT"

echo "0. 加载Canonical 90基线..."
CANONICAL_FILE="$PROJECT_DIR/src/test/resources/permission/canonical-permissions-90.txt"
if [ -f "$CANONICAL_FILE" ]; then
    grep -v '^#' "$CANONICAL_FILE" | grep -v '^$' | sort -u > "$CANONICAL_PERMS" || true
fi
CANONICAL_COUNT=$(wc -l < "$CANONICAL_PERMS")
echo "   Canonical基线权限码数量: $CANONICAL_COUNT"

echo "1. 提取前端权限码..."
# 提取前端权限码（从roles.ts）
# 支持多段格式: module.resource[.subresource].operation[.suboperation].dataScope
# 例如: approval.index.batch.transfer.ALL (5段), dashboard.chart.realtime.ALL (4段)
grep -oE "'[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+'" "$PROJECT_DIR/frontend/admin/src/auth/roles.ts" 2>/dev/null | \
    sed "s/'//g" | sort -u > "$FRONTEND_PERMS" || true

# 也支持双引号
grep -oE '"[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+"' "$PROJECT_DIR/frontend/admin/src/auth/roles.ts" 2>/dev/null | \
    sed 's/"//g' >> "$FRONTEND_PERMS" || true

sort -u "$FRONTEND_PERMS" -o "$FRONTEND_PERMS"
FRONTEND_COUNT=$(wc -l < "$FRONTEND_PERMS")
echo "   前端权限码数量: $FRONTEND_COUNT"

echo "2. 提取数据库权限码..."
# 提取数据库权限码（从SQL迁移脚本）
# 支持多段格式: module.resource[.subresource].operation[.suboperation].dataScope
grep -oE "'[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+'" "$PROJECT_DIR/src/main/resources/db/migration/V26__Seed_roles_permissions.sql" 2>/dev/null | \
    sed "s/'//g" > "$DB_PERMS" || true

# 从其他迁移脚本补充
for sql in "$PROJECT_DIR/src/main/resources/db/migration"/V*.sql; do
    grep -oE "'[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+'" "$sql" 2>/dev/null | sed "s/'//g" >> "$DB_PERMS" || true
done
sort -u "$DB_PERMS" -o "$DB_PERMS"
DB_COUNT=$(wc -l < "$DB_PERMS")
echo "   数据库权限码总数: $DB_COUNT"

echo "3. 提取后端权限码..."
# 提取后端权限码（从RequirePermission注解）
# 支持直接字符串: @RequirePermission("approval.index.view.ALL")
# 支持多段格式: module.resource[.subresource].operation[.suboperation].dataScope
grep -r "RequirePermission" "$PROJECT_DIR/src/main/java" --include="*.java" 2>/dev/null | \
    grep -oE '"[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+"' | sed 's/"//g' >> "$BACKEND_PERMS" || true

# 支持常量引用: @RequirePermission(PERM_XXX) - 需要进一步处理常量定义
# 找出所有常量定义
grep -r "private static final String PERM_" "$PROJECT_DIR/src/main/java" --include="*.java" 2>/dev/null | \
    grep -oE 'PERM_[A-Z_]+ = "[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+"' | \
    sed 's/.*= *"/"/g' | sed 's/"//g' >> "$BACKEND_PERMS" || true

sort -u "$BACKEND_PERMS" -o "$BACKEND_PERMS"
BACKEND_COUNT=$(wc -l < "$BACKEND_PERMS")
echo "   后端权限码数量: $BACKEND_COUNT"

echo ""
echo "4. 生成差异报告..."

# 计算差异
comm -23 "$FRONTEND_PERMS" "$CANONICAL_PERMS" > "$SCRIPT_DIR/.frontend_only.txt" || true
comm -23 "$DB_PERMS" "$CANONICAL_PERMS" > "$SCRIPT_DIR/.db_only.txt" || true
comm -23 "$BACKEND_PERMS" "$CANONICAL_PERMS" > "$SCRIPT_DIR/.backend_only.txt" || true
comm -23 "$CANONICAL_PERMS" "$FRONTEND_PERMS" > "$SCRIPT_DIR/.canonical_not_in_frontend.txt" || true
comm -23 "$CANONICAL_PERMS" "$DB_PERMS" > "$SCRIPT_DIR/.canonical_not_in_db.txt" || true
comm -23 "$CANONICAL_PERMS" "$BACKEND_PERMS" > "$SCRIPT_DIR/.canonical_not_in_backend.txt" || true

FRONTEND_ONLY=$(wc -l < "$SCRIPT_DIR/.frontend_only.txt")
DB_ONLY=$(wc -l < "$SCRIPT_DIR/.db_only.txt")
BACKEND_ONLY=$(wc -l < "$SCRIPT_DIR/.backend_only.txt")
CANONICAL_NOT_IN_FRONTEND=$(wc -l < "$SCRIPT_DIR/.canonical_not_in_frontend.txt")
CANONICAL_NOT_IN_DB=$(wc -l < "$SCRIPT_DIR/.canonical_not_in_db.txt")
CANONICAL_NOT_IN_BACKEND=$(wc -l < "$SCRIPT_DIR/.canonical_not_in_backend.txt")

# 写入报告
cat > "$DIFF_REPORT" << EOF
# 权限码一致性校验报告

生成时间: $(date '+%Y-%m-%d %H:%M:%S')

## 四维统计

| 来源 | 权限码数量 |
|------|------------|
| Canonical基线 | $CANONICAL_COUNT |
| 前端 | $FRONTEND_COUNT |
| 数据库 | $DB_COUNT |
| 后端 | $BACKEND_COUNT |

## Canonical基线覆盖率

| 维度 | 缺失数量 | 说明 |
|------|----------|------|
| 前端缺失 | $CANONICAL_NOT_IN_FRONTEND | Canonical基线在前端未定义 |
| 数据库缺失 | $CANONICAL_NOT_IN_DB | Canonical基线在数据库未导入 |
| 后端缺失 | $CANONICAL_NOT_IN_BACKEND | Canonical基线在后端未使用 |

## 额外权限码分析（不在Canonical基线中）

### 前端独有权限码 (不在Canonical基线中): $FRONTEND_ONLY
EOF

if [ $FRONTEND_ONLY -gt 0 ]; then
    echo "" >> "$DIFF_REPORT"
    cat "$SCRIPT_DIR/.frontend_only.txt" >> "$DIFF_REPORT"
    echo "" >> "$DIFF_REPORT"
fi

cat >> "$DIFF_REPORT" << EOF

### 数据库独有权限码 (不在Canonical基线中): $DB_ONLY
EOF

if [ $DB_ONLY -gt 0 ]; then
    echo "" >> "$DIFF_REPORT"
    cat "$SCRIPT_DIR/.db_only.txt" >> "$DIFF_REPORT"
    echo "" >> "$DIFF_REPORT"
fi

cat >> "$DIFF_REPORT" << EOF

### 后端独有权限码 (不在Canonical基线中): $BACKEND_ONLY
EOF

if [ $BACKEND_ONLY -gt 0 ]; then
    echo "" >> "$DIFF_REPORT"
    cat "$SCRIPT_DIR/.backend_only.txt" >> "$DIFF_REPORT"
    echo "" >> "$DIFF_REPORT"
fi

cat >> "$DIFF_REPORT" << EOF

## Canonical基线缺失项

### 前端未覆盖Canonical基线 ($CANONICAL_NOT_IN_FRONTEND)
EOF

if [ $CANONICAL_NOT_IN_FRONTEND -gt 0 ]; then
    echo "" >> "$DIFF_REPORT"
    cat "$SCRIPT_DIR/.canonical_not_in_frontend.txt" >> "$DIFF_REPORT"
    echo "" >> "$DIFF_REPORT"
fi

cat >> "$DIFF_REPORT" << EOF

### 数据库未导入Canonical基线 ($CANONICAL_NOT_IN_DB)
EOF

if [ $CANONICAL_NOT_IN_DB -gt 0 ]; then
    echo "" >> "$DIFF_REPORT"
    cat "$SCRIPT_DIR/.canonical_not_in_db.txt" >> "$DIFF_REPORT"
    echo "" >> "$DIFF_REPORT"
fi

cat >> "$DIFF_REPORT" << EOF

### 后端未实现Canonical基线 ($CANONICAL_NOT_IN_BACKEND)
EOF

if [ $CANONICAL_NOT_IN_BACKEND -gt 0 ]; then
    echo "" >> "$DIFF_REPORT"
    cat "$SCRIPT_DIR/.canonical_not_in_backend.txt" >> "$DIFF_REPORT"
    echo "" >> "$DIFF_REPORT"
fi

# 判断是否通过 - 以Canonical基线为基准
if [ $CANONICAL_NOT_IN_FRONTEND -eq 0 ] && [ $CANONICAL_NOT_IN_DB -eq 0 ] && [ $CANONICAL_NOT_IN_BACKEND -eq 0 ]; then
    echo ""
    echo "✅ 权限码一致性校验通过！Canonical基线已完整覆盖。"
    RESULT=0
else
    echo ""
    echo "❌ 权限码一致性校验未通过，请查看差异报告: $DIFF_REPORT"
    echo "   Canonical基线缺失 - 前端: $CANONICAL_NOT_IN_FRONTEND"
    echo "   Canonical基线缺失 - 数据库: $CANONICAL_NOT_IN_DB"
    echo "   Canonical基线缺失 - 后端: $CANONICAL_NOT_IN_BACKEND"
    RESULT=1
fi

# 清理临时文件
rm -f "$SCRIPT_DIR/.frontend_only.txt" "$SCRIPT_DIR/.db_only.txt" "$SCRIPT_DIR/.backend_only.txt"
rm -f "$SCRIPT_DIR/.canonical_not_in_frontend.txt" "$SCRIPT_DIR/.canonical_not_in_db.txt" "$SCRIPT_DIR/.canonical_not_in_backend.txt"

exit $RESULT