#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
K/L 分工自检 / K-L Column Separation Check
==========================================
校区梳理表 Step5 终审必跑：验证 K 列(法律风险) 与 L 列(模版差异) 职责分离。

  · K 列(第 11 列)= 独立法律审查，从合同条款本身起笔，**绝不引模版**
        → 不得出现 "模版 / 07模版 / 07-房屋 / 07标准 / 相对模版 / 被放宽 / 被删除 / 被改为"
  · L 列(第 12 列)= 纯客观文本对比，只陈述 "模版表述为X；本合同表述为Y"
        → 不得出现 "风险 / 建议 / 不利 / 详见"(判断词与向 K 列导流的话)

⚠️ K 列匹配 "07模版 / 07-房屋 / 07标准" 而非裸 "07"——裸 07 会误命中金额数字
   (如租金 377,507.80 里的 "507")，2026-06-24 跃龙路实证误报，已修正。

判据·遮模版测试：把"模版怎么写"整个遮住，K 列那条风险论述仍完整成立才算独立审查；
遮住就垮 = L 列逻辑混进了 K 列。

用法：
    python3 kl-separation-check.py <校区梳理表.xlsx>
退出码：0 = 通过；1 = 有违规(需回去拆分 K/L)；2 = 用法错误

注：本脚本只查 K(11)/L(12) 两列的数据行。整体段(合并 A:L，在第 1 列)里
    "【与07标准模版的文本差异】" 小节合法含"模版/07"，不在本脚本检查范围——
    那是整体段按设计单独成段的客观对比，不是 K 列。
"""
import sys
import re
import openpyxl

K_FORBIDDEN_LITERAL = ["模版", "相对模版", "被放宽", "被删除", "被改为"]
K_FORBIDDEN_REGEX = r"07模版|07-?房屋|07标准"
L_FORBIDDEN_LITERAL = ["风险", "建议", "不利", "详见"]


def cell_text(cell):
    """取单元格纯文本，兼容 CellRichText(可迭代) 与标量。"""
    v = cell.value
    if v is None:
        return ""
    if isinstance(v, str):
        return v
    try:
        return "".join(getattr(t, "text", str(t)) for t in v)
    except TypeError:
        return str(v)


def is_header(text):
    """表头行启发式：K 表头='法律风险…'/'风险点…'；L 表头='与…模版差异'。"""
    head = text[:10]
    if ("法律风险" in head or "风险点" in head) and len(text) < 40:
        return True
    if text.startswith("与") and "模版差异" in text and len(text) < 40:
        return True
    return False


def check(path):
    wb = openpyxl.load_workbook(path)
    violations = []
    for ws in wb.worksheets:
        for r in range(1, ws.max_row + 1):
            k = cell_text(ws.cell(r, 11))
            l = cell_text(ws.cell(r, 12))
            if k and not is_header(k):
                kb = [w for w in K_FORBIDDEN_LITERAL if w in k]
                kb += re.findall(K_FORBIDDEN_REGEX, k)
                if kb:
                    violations.append((ws.title, f"K{r}", "独立审查不得引模版", kb))
            if l and not is_header(l):
                lb = [w for w in L_FORBIDDEN_LITERAL if w in l]
                if lb:
                    violations.append((ws.title, f"L{r}", "纯客观对比不得下判断", lb))
    return violations


def main():
    if len(sys.argv) < 2:
        print("用法: python3 kl-separation-check.py <校区梳理表.xlsx>")
        sys.exit(2)
    v = check(sys.argv[1])
    if not v:
        print("✅ K/L 分工自检通过：K 列零模版引用、L 列零判断词。")
        sys.exit(0)
    print("❌ K/L 分工自检发现违规（需回去拆分）：")
    for sheet, cell, why, hits in v:
        print(f"  [{sheet}] {cell}: {why} — 命中 {hits}")
    print("\n判据·遮模版测试：把'模版怎么写'遮住，K 列风险论述仍完整成立才算独立。")
    print("L 列只陈述'模版表述为X；本合同表述为Y'，判断与建议归 K 列。")
    sys.exit(1)


if __name__ == "__main__":
    main()
