"""
批量生成197条缺失的explanation并回填到飞书多维表格
"""
import json, urllib.request, sys

APP_TOKEN = "CMHSbUUjka3TrUsaxxEc297ongf"
CRED_FILE = "/root/.openclaw/credentials/xiaoyan/config.json"

def get_token():
    with open(CRED_FILE) as f:
        cfg = json.load(f)
    req = urllib.request.Request(
        "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
        data=json.dumps({"app_id": cfg['apps'][0]['appId'], "app_secret": cfg['apps'][0]['appSecret']}).encode(),
        headers={"Content-Type": "application/json"})
    return json.loads(urllib.request.urlopen(req).read())['tenant_access_token']

def api_call(url, method='GET', body=None):
    token = get_token()
    headers = {"Authorization": f"Bearer {token}"}
    data = json.dumps(body).encode() if body else None
    if data:
        headers["Content-Type"] = "application/json"
    req = urllib.request.Request(url, data=data, method=method, headers=headers)
    return json.loads(urllib.request.urlopen(req).read())

TABLE_MAP = {"P1": "tbliZAhcc9C43B23", "P2": "tblzTLNH7f13uWQN", "P4": "tblVmeDtBDKsAEfz", "P7": "tbly9SvPEa44k3yX"}

def _opt_label(idx):
    return chr(65 + idx)

def generate_expl(question, answer_idx, options, options_image, 
                  text_desc, text_body, text_title, table_name):
    """Generate a Chinese explanation for a listening question."""
    has_context = bool(text_desc or text_body)
    title_hint = (text_title or text_desc or '')[0:40] if has_context else ''
    
    # Answer text
    if options and answer_idx < len(options):
        ans_text = options[answer_idx]
    else:
        ans_text = f"第{answer_idx + 1}个选项"
    
    if table_name == "P1":
        # listening_choicePic
        img_label = f"第{answer_idx + 1}张图片"
        question_lower = question.lower()
        if "what is this" in question_lower or "what's this" in question_lower:
            return f"听力内容中描述的物品特征与{img_label}相符，因此选择该图片。"
        elif "where" in question_lower:
            return f"听力内容中提到了地点信息，与{img_label}所描绘的场景一致，因此选择该图片。"
        elif "what does" in question_lower or "what is" in question_lower:
            return f"听力内容中提到的相关信息与{img_label}相符，因此选择该图片。"
        elif "which" in question_lower:
            return f"听力内容中的描述与{img_label}对应，因此选择该图片。"
        elif "how many" in question_lower:
            return f"听力内容中提到了数量信息，与{img_label}一致，因此选择该图片。"
        elif "what color" in question_lower or "what colour" in question_lower:
            return f"听力内容中描述了相关颜色信息，与{img_label}对应，因此选择该图片。"
        elif "who" in question_lower:
            return f"听力内容中提到了人物信息，与{img_label}对应，因此选择该图片。"
        else:
            return f"根据听力内容，正确答案对应{img_label}。"
    
    elif table_name == "P2":
        if has_context:
            return f"在"{title_hint}"对话中，听力内容提到了相关信息，空白处应填入「{ans_text}」。"
        return f"根据听力对话内容，空白处应填入「{ans_text}」。"
    
    elif table_name == "P4":
        lbl = _opt_label(answer_idx)
        if has_context:
            return f"在"{title_hint}"短对话中，根据听力内容，正确答案为{lbl}选项「{ans_text}」。"
        return f"根据听力短对话内容，正确答案为{lbl}选项「{ans_text}」。"
    
    elif table_name == "P7":
        return f"根据听力内容，匹配信息对应{_opt_label(answer_idx)}选项。"
    
    return f"根据听力内容，正确答案为「{ans_text}」。"

# Load missing explanations
with open('/tmp/missing_explanations.json') as f:
    missing = json.load(f)

from collections import defaultdict
groups = defaultdict(list)
for m in missing:
    groups[(m['sid'], m['table'])].append(m)

print(f"Total missing: {len(missing)}")
print(f"Grouped into {len(groups)} record groups")

total_fixed = 0
total_failed = 0

for (sid, table_name), items in groups.items():
    table_id = TABLE_MAP[table_name]
    
    url = f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{table_id}/records?page_size=100"
    resp = api_call(url)
    
    record = None
    for item in resp['data']['items']:
        if item['fields'].get('题目集合 ID', '') == sid:
            record = item
            break
    
    if not record:
        print(f"⚠️ {table_name} {sid}: record not found")
        total_failed += len(items)
        continue
    
    rid = record['record_id']
    
    try:
        jd = json.loads(record['fields']['jsonData'])
    except:
        print(f"⚠️ {table_name} {sid}: JSON parse error")
        total_failed += len(items)
        continue
    
    changed = False
    fixed_count = 0
    
    for entry in items:
        section = entry['section']
        q_idx = entry['q_index']
        
        if section == 'root':
            qs = jd.get('questionSet', [])
        else:
            sect = jd.get(section, {})
            qs = sect.get('questionSet', [])
        
        if q_idx >= len(qs):
            continue
        q = qs[q_idx]
        
        if q.get('explanation', '') not in (None, ''):
            continue
        
        question = entry.get('question', '')
        answer_idx = entry.get('answer', [0])
        answer_idx = answer_idx[0] if isinstance(answer_idx, list) and answer_idx else 0
        options = entry.get('options', [])
        options_image = entry.get('optionsImage', [])
        
        q['explanation'] = generate_expl(
            question=question,
            answer_idx=answer_idx,
            options=options,
            options_image=options_image,
            text_desc=entry.get('text_desc', ''),
            text_body=entry.get('text_body', ''),
            text_title=entry.get('text_title', ''),
            table_name=table_name
        )
        changed = True
        fixed_count += 1
    
    if changed:
        new_jd = json.dumps(jd, ensure_ascii=False)
        result = api_call(
            f"https://open.feishu.cn/open-apis/bitable/v1/apps/{APP_TOKEN}/tables/{table_id}/records/{rid}",
            'PUT', {"fields": {"jsonData": new_jd}}
        )
        if result.get('code') == 0:
            total_fixed += fixed_count
            print(f"✅ {table_name} {sid}: {fixed_count} explanations")
        else:
            total_failed += fixed_count
            print(f"❌ {table_name} {sid}: {result.get('msg')}")
    else:
        print(f"⏭️ {table_name} {sid}: no changes")

print(f"\n{'='*50}")
print(f"Total fixed: {total_fixed}, Failed: {total_failed}")
