#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""分批生成相似问法（修复版）：
- items 显式注入全局 _i = start+i（不依赖调用前状态）
- tmp 文件用随机后缀，避免多进程并发覆盖
- grok 返回键 = 全局序号 _i
"""
import json, os, subprocess, sys, re, uuid, glob

BASE = "/home/zyw/Downloads/dl-hub/01-AI课程设计项目/知识库问答库"
ALL = json.load(open(os.path.join(BASE, "题目全集.json"), encoding='utf-8'))
S = os.path.expanduser("~/.dsh/skills/grok-run/scripts/grok-run.sh")

def batch_prompt(items):
    lines = []
    for it in items:
        q = it["q"]
        qc = re.sub(r'```python.*?```', '【代码见原题】', q, flags=re.S)
        if len(qc) > 110: qc = qc[:107] + "…"
        lines.append(f'{it["_i"]}|{qc}')
    body = "\n".join(lines)
    return ("你是AI课程问答库编辑。下面每行是「题目序号|标准问题」，请为每一题生成 3 条【相似问法】（学生可能用的等价问法：换措辞、换句式、口语化均可，但不能改变答案语义，不能变反义，不能把单选变多选）。"
            "只输出一个 JSON 对象：键为题目序号，值为长度 3 的字符串数组，每条 ≤80 字；JSON 必须完整包含全部给出的题目序号。除 JSON 外不要输出任何其他内容。若题目过多可分多个 JSON 对象输出。\n\n" + body)

def run_batch(items, out_path):
    tmp = f"/tmp/sim-{uuid.uuid4().hex[:10]}.json"
    prompt = batch_prompt(items)
    r = subprocess.run(["bash", S, prompt, "--out", tmp, "--max-turns", "30"],
                       capture_output=True, text=True, timeout=1200)
    txt = ""
    for cand in (tmp, tmp + ".final-text.txt"):
        if os.path.exists(cand):
            try:
                txt = open(cand, encoding='utf-8').read()
                if txt.strip(): break
            except Exception: pass
    if not txt.strip():
        print("!! 无输出", r.stderr[-200:] if r.stderr else ""); return False
    # 提取所有 JSON 对象（可能多个）
    data = {}
    for m in re.finditer(r'\{[^{}]*\{[^{}]*\}.*?\}', txt, re.S):
        pass
    # 简单方式：找所有 {..} 并逐个解析，收集键值
    for m in re.finditer(r'"(\d+)"\s*:\s*\[(.*?)\]', txt, re.S):
        k = m.group(1)
        vals = re.findall(r'"((?:[^"\\]|\\.)*)"', m.group(2))
        if k not in data and len(vals) >= 2:
            data[k] = [v.replace('\\"','"').replace('\\\\','\\') for v in vals]
    if not data:
        print("!! 无有效JSON键值", txt[:200]); return False
    # 校验覆盖
    missing = [str(it["_i"]) for it in items if str(it["_i"]) not in data]
    if missing:
        print(f"!! 缺 {len(missing)} 个键: {missing[:5]}…")
        # 失败则重试一次（加大 max-turns）
        r2 = subprocess.run(["bash", S, prompt + "\n注意：上一次缺少部分序号，请务必为所有给出的序号各输出3条。", "--out", tmp+"2", "--max-turns", "40"],
                            capture_output=True, text=True, timeout=1200)
        txt2 = ""
        for cand in (tmp+"2", tmp+"2.final-text.txt"):
            if os.path.exists(cand):
                try:
                    txt2 = open(cand, encoding='utf-8').read()
                    if txt2.strip(): break
                except Exception: pass
        for m in re.finditer(r'"(\d+)"\s*:\s*\[(.*?)\]', txt2, re.S):
            k = m.group(1)
            vals = re.findall(r'"((?:[^"\\]|\\.)*)"', m.group(2))
            if k not in data and len(vals) >= 2:
                data[k] = [v.replace('\\"','"').replace('\\\\','\\') for v in vals]
        missing2 = [str(it["_i"]) for it in items if str(it["_i"]) not in data]
        if missing2:
            print(f"!! 重试后仍缺 {len(missing2)}: {missing2[:5]}…")
    with open(out_path, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=1)
    return True

if __name__ == "__main__":
    start = int(sys.argv[1]); size = int(sys.argv[2]); out = sys.argv[3]
    batch = ALL[start:start+size]
    for i, it in enumerate(batch):
        it["_i"] = start + i
    ok = run_batch(batch, out)
    print("OK" if ok else "FAIL", "批次", start, "-", start+len(batch)-1, "键数:", end=" ")
    try:
        print(len(json.load(open(out, encoding='utf-8'))))
    except Exception: print(0)