#!/usr/bin/env python3
"""
OCR乱码检测器 — Step1 OCR完成后必跑。
扫描OCR文本中所有疑似乱码行，输出vision核实清单。
每一处乱码都必须vision对应PDF页面核实后才能进Step2。

用法: python3 ocr-garble-detect.py <ocr_file.md>

判定规则：
  1. 多个无意义英文片段（连续3+字母非常见词）
  2. 中文占比过低（正常合同行>50%，低于30%标红）
  3. 中英混杂碎片（典型OCR乱码模式）
  4. 异常符号密集（>20%非正常字符）

误报处理：
  - 纯数字表格行（日期+金额）→ 正常，核对数字即可
  - 邮箱/网址/银行账号 → 正常
  - 英文缩写（USD/RMB/PDF）→ 正常
  真正需要vision的是：含中文碎片+英文乱码的混合行（如"oe方,同Se"）

教训(凤凰文化0701)：
  Line 204 "Se【2024】年【10】月【15】日" 被跳过未核实，
  导致整段违约金条款丢失（实际是"初年年租金20%作为违约金"）。
  代价=审查结论反转（"无违约金"→"有20%违约金"）。
"""
import re, sys

def is_garbled(line):
    """判断一行是否疑似乱码，返回原因或None"""
    stripped = line.strip()
    if not stripped or len(stripped) < 5:
        return None
    
    # 1. 连续3+个无意义英文字母组合（非常见英文词）
    nonsense_en = re.findall(r'[a-zA-Z]{3,}', stripped)
    common_words = {'pdf','ocr','usd','rmb','the','and','for','with','from',
                    'www','com','xdf','jpg','png','doc','docx','xlsx','occ',
                    'vision','step','check','null','true','false'}
    real_nonsense = [w for w in nonsense_en 
                     if w.lower() not in common_words 
                     and not re.match(r'^[A-Z]{1,4}$', w)]
    if len(real_nonsense) >= 2:
        return f"多个无意义英文片段: {real_nonsense[:3]}"
    
    # 2. 单行中文字符占比过低（正常合同行中文应>50%）
    chinese_chars = len(re.findall(r'[\u4e00-\u9fff]', stripped))
    total_chars = len(re.findall(r'\S', stripped))
    if total_chars > 10 and chinese_chars / total_chars < 0.3:
        # 排除纯数字表格行（日期+金额）和邮箱/账号行
        if re.match(r'^[\d\.\-\s\|/,]+$', stripped):
            return None  # 纯数字表格行
        if '@' in stripped or re.match(r'^[A-Z]{2,4}:', stripped):
            return None  # 邮箱或字段标签
        return f"中文占比过低({chinese_chars}/{total_chars}={chinese_chars/total_chars:.0%})"
    
    # 3. 常见OCR乱码模式：小写英文碎片+中文混杂
    if re.search(r'[a-z]{2,}\s+[a-z]{2,}\s+[a-z]{2,}', stripped) and chinese_chars > 0:
        return "中英混杂碎片（典型OCR乱码）"
    
    # 3b. 日期区域英文字母污染（凤凰文化10.2教训：Se【2024】年【10】月→整段丢失）
    if re.search(r'[A-Za-z]{2,}\s*【\d{4}】', stripped) and chinese_chars > 0:
        return "日期区域字母污染（高风险：可能整段条款被OCR吃掉）"
    
    # 4. 特殊符号异常密集
    special = len(re.findall(r'[^\w\u4e00-\u9fff\s，。、；：""''（）【】《》\-\+\.\%\/\|]', stripped))
    if special > 5 and total_chars > 0 and special / total_chars > 0.2:
        return f"异常符号密集({special}个)"
    
    return None


def main():
    if len(sys.argv) < 2:
        print("用法: python3 ocr-garble-detect.py <ocr_file.md>")
        sys.exit(1)
    
    filepath = sys.argv[1]
    with open(filepath, 'r') as f:
        lines = f.readlines()
    
    garbled = []
    for i, line in enumerate(lines, 1):
        reason = is_garbled(line)
        if reason:
            garbled.append((i, line.strip()[:80], reason))
    
    if not garbled:
        print("✅ 未检测到明显乱码行。可以进入Step 2。")
    else:
        # 区分真乱码 vs 可能误报（纯数字/邮箱等）
        real_garble = [g for g in garbled if '无意义英文' in g[2] or '中英混杂' in g[2]]
        maybe_garble = [g for g in garbled if g not in real_garble]
        
        print(f"⚠️  检测到 {len(garbled)} 处疑似乱码（其中 {len(real_garble)} 处高危）\n")
        
        if real_garble:
            print("🔴 高危乱码（必须vision核实，不核实不进Step2）：")
            for lineno, text, reason in real_garble:
                print(f"  Line {lineno:3d} | {reason}")
                print(f"           | {text}")
                print()
        
        if maybe_garble:
            print("🟡 疑似乱码（核对数字/格式是否正确）：")
            for lineno, text, reason in maybe_garble:
                print(f"  Line {lineno:3d} | {reason}")
                print(f"           | {text}")
                print()
        
        print(f"--- 高危 {len(real_garble)} 处必须vision核实 + 疑似 {len(maybe_garble)} 处核对数值 ---")
        print("操作：对每处高危乱码，定位PDF页码 → vision精读 → 记录修正内容")
        print("全部消灭后才能进入 Step 2。")


if __name__ == '__main__':
    main()
