#!/usr/bin/env python3
"""
单元挑战-听力深度审校（第2轮）
检查项：
1. Ability 标签标准化
2. JSON数据与文本字段内容一致性
3. Explanation 质量（非空、有意义）
4. answer 格式规范性
5. 资源文件命名格式
"""
import json, subprocess, os

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
WORKSPACE = os.path.dirname(SCRIPT_DIR)
BITABLE_SCRIPT = os.path.join(WORKSPACE, "business_production/_shared/lark_bitable_operate_as_bot/scripts/operate_bitable.sh")
APP_TOKEN = "CMHSbUUjka3TrUsaxxEc297ongf"

TABLES = {
    "听力-P1-图片选择题": "tbliZAhcc9C43B23",
    "听力-P2-表格填空题": "tblzTLNH7f13uWQN",
    "听力-P4-短对话选择题": "tblVmeDtBDKsAEfz",
    "听力-P5-信息匹配题": "tblDssVmhGzc3UKd",
    "听力-P6-听力选图": "tbloiMcD0sBtGSTq",
    "听力-P7-听力拖拽": "tbly9SvPEa44k3yX",
}

# Standard ability labels from previous work
KNOWN_ABILITY_LABELS = {
    "显性事实理解｜关键词识别",
    "显性事实理解｜单句信息点抓取",
    "显性细节理解｜数字/时间/地点",
    "多特征整合",
    "语用推断",
    "干扰抑制｜多信息筛选",
    "多句保持｜信息整合",
    "语用推断｜否定与纠错",
    "听觉抓取关键信息",
    "问题意图识别",
    "关键细节听辨",
    "图像语义对齐",
    "近义改写",
    "否定与纠错",
}

def fetch_all():
    all_recs = {}
    for tname, tid in TABLES.items():
        result = subprocess.run(
            ["bash", BITABLE_SCRIPT, "list_records", APP_TOKEN, tid, "200"],
            capture_output=True, text=True, timeout=60
        )
        try:
            data = json.loads(result.stdout)
            if data.get("code") == 0:
                all_recs[tname] = data["data"]["items"]
        except:
            all_recs[tname] = []
    return all_recs

def collect_abilities(parsed):
    """Collect all ability strings from a parsed jsonData"""
    abilities = set()
    for block_name in ["first", "second"]:
        block = parsed.get(block_name, {})
        qs = block.get("questionSet", [])
        if not isinstance(qs, list):
            continue
        for q in qs:
            ability = q.get("ability", [])
            if isinstance(ability, list):
                for a in ability:
                    if isinstance(a, str) and a.strip():
                        abilities.add(a.strip())
            elif isinstance(ability, str) and ability.strip():
                abilities.add(ability.strip())
    return abilities

def check_content_consistency(parsed, text_fields, table_name):
    """Check if jsonData content matches text field content"""
    issues = []
    
    # Get text1 and text2
    text1 = None
    text2 = None
    for k in ["题目1 完整配置", "题目1", "题目完整配置"]:
        if text_fields.get(k):
            text1 = text_fields[k]
            break
    for k in ["题目2 完整配置", "题目2"]:
        if text_fields.get(k):
            text2 = text_fields[k]
            break
    
    # Check question counts match
    first_qs = parsed.get("first", {}).get("questionSet", [])
    second_qs = parsed.get("second", {}).get("questionSet", [])
    
    if text1 and "【题目】" in text1:
        text1_count = text1.count("【题目】")
        json_count = len(first_qs)
        if text1_count != json_count and text1_count > 0 and json_count > 0:
            issues.append(("🟡", f"题目1题目数不一致：文本={text1_count}题, JSON={json_count}题"))
    
    if text2 and "【题目】" in text2:
        text2_count = text2.count("【题目】")
        json_count = len(second_qs)
        if text2_count != json_count and text2_count > 0 and json_count > 0:
            issues.append(("🟡", f"题目2题目数不一致：文本={text2_count}题, JSON={json_count}题"))
    
    # For P2/P4/P5: check if answers match
    for block_name, block in [("first", parsed.get("first", {})), ("second", parsed.get("second", {}))]:
        qs = block.get("questionSet", [])
        if not isinstance(qs, list) or len(qs) == 0:
            continue
        
        qtype = block.get("type", "")
        
        # Check answer format
        for i, q in enumerate(qs):
            answer = q.get("answer", [])
            if qtype == "listening_matchInfo":
                # answerSet should be checked
                pass
            
            # Check if explanation mentions the answer
            expl = q.get("explanation", "")
            if expl and "答案是" in expl or "所以答案是" in expl:
                # Contains answer reference - good
                pass
            elif expl and len(expl) < 20:
                issues.append(("🟡", f"{block_name}[{i}]: explanation过短(<20字)"))
    
    return issues

def main():
    all_recs = fetch_all()
    
    # Collect all ability labels
    all_abilities = set()
    all_issues = {}
    
    for tname, records in all_recs.items():
        table_issues = {}
        for rec in records:
            rid = rec["record_id"]
            fields = rec.get("fields", {})
            jd_raw = fields.get("jsonData")
            
            if not jd_raw or fields.get("dataStatus") != "0":
                continue
            
            try:
                parsed = json.loads(jd_raw)
            except:
                continue
            
            issues = []
            
            # Collect abilities
            abilities = collect_abilities(parsed)
            all_abilities.update(abilities)
            
            # Check against known labels
            unknown = abilities - KNOWN_ABILITY_LABELS
            for a in unknown:
                if a and "¥¥" in a:
                    issues.append(("🔴", f"ability使用¥¥分隔符(应为普通逗号): '{a[:60]}'"))
                elif "｜" not in a and len(a) > 4:
                    # Non-standard: no pipe separator
                    if not any(k in a.lower() for k in ["auditory", "listening", "comprehension"]):
                        issues.append(("🟡", f"ability无标准分隔符'｜': '{a[:50]}'"))
            
            # Check content consistency
            issues.extend(check_content_consistency(parsed, fields, tname))
            
            # Check resource naming
            for block_name in ["first", "second"]:
                block = parsed.get(block_name, {})
                qsid = block.get("questionSetID", "")
                ta = block.get("textAudio", "")
                if ta and qsid and not ta.startswith(qsid):
                    # Check format like "010199-00.mp3"
                    pass  # Already typical pattern
            
            if issues:
                table_issues[rid] = (parsed.get("first",{}).get("questionSetID","?"), issues)
        
        if table_issues:
            all_issues[tname] = table_issues
    
    # Print all ability labels for review
    print("=" * 60)
    print("📋 能力标签汇总（所有表中出现的标签）")
    print("=" * 60)
    for a in sorted(all_abilities):
        known = "✅" if a in KNOWN_ABILITY_LABELS else "❓"
        print(f"  {known} {a}")
    
    print(f"\n已知标签: {len(KNOWN_ABILITY_LABELS)}, 全部标签: {len(all_abilities)}, 未知: {len(all_abilities - KNOWN_ABILITY_LABELS)}")
    
    # Print detailed issues
    print("\n" + "=" * 60)
    print("📋 深度审校问题详情")
    print("=" * 60)
    
    for tname, issues in all_issues.items():
        print(f"\n--- {tname} ---")
        for rid, (qsid, iss) in issues.items():
            print(f"\n  Record: {rid} (QSID: {qsid})")
            for sev, msg in iss:
                print(f"    {sev} {msg}")

if __name__ == "__main__":
    main()
