#!/usr/bin/env python3
import argparse
import json
import re
import sys
import os
from typing import List, Dict

# 角色名称库
CHARACTERS = ["Otis", "Ben", "Skylar", "Brainy", "Daisy", "Jim", "Paul", "Fred"]

# 共用L1单词库路径
WORD_LIST_PATH = os.path.join(os.path.dirname(__file__), "../../listening-drag/references/l1_word_list.json")

# 难度对应规则
DIFFICULTY_RULES = {
    "A": {
        "sentence_length": "≤5词",
        "interference": "选项类别完全不同，差异极大",
        "description": "简单句，关键词后置，无修饰成分"
    },
    "B": {
        "sentence_length": "≤8词",
        "interference": "同类别不同属性（颜色/大小）",
        "description": "简单句，可带1个形容词修饰"
    },
    "C": {
        "sentence_length": "≤12词",
        "interference": "同物品不同动作/状态",
        "description": "简单句，可带介词短语修饰"
    },
    "D": {
        "sentence_length": "≤15词",
        "interference": "同场景不同逻辑",
        "description": "带简单从句，可包含逻辑连接词"
    }
}

def parse_args():
    parser = argparse.ArgumentParser(description="Generate Listening Picture Choice questions")
    parser.add_argument("--knowledge", required=True, help="知识点列表，分号分隔")
    parser.add_argument("--difficulty", required=True, choices=["A", "B", "C", "D"], help="难度等级")
    parser.add_argument("--count", type=int, default=1, help="生成题目数量，默认1道")
    parser.add_argument("--scene", default="", help="题目场景要求，可选")
    return parser.parse_args()

def load_word_list() -> List[str]:
    """加载L1单词库"""
    try:
        with open(WORD_LIST_PATH, "r", encoding="utf-8") as f:
            data = json.load(f)
            return [word["word"].lower() for word in data["words"]]
    except Exception as e:
        print(f"警告：加载单词库失败，跳过超纲校验：{str(e)}", file=sys.stderr)
        return []

def validate_knowledge_with_wordlist(knowledge: str, word_list: List[str]) -> bool:
    """校验知识点是否在单词库中"""
    if not word_list:
        return True
    knowledge_words = [item.split()[0].lower() for item in knowledge.split(";") if item.strip()]
    out_of_range = []
    for word in knowledge_words:
        if word not in word_list:
            out_of_range.append(word)
    if out_of_range:
        print(f"错误：以下知识点超纲，不在L1单词库中：{','.join(out_of_range)}", file=sys.stderr)
        return False
    return True

def validate_input(args) -> bool:
    """校验输入参数合法性"""
    if not args.knowledge.strip():
        print("错误：知识点不能为空", file=sys.stderr)
        return False
    if args.count < 1 or args.count > 10:
        print("错误：题量范围1-10道", file=sys.stderr)
        return False
    # 超纲校验
    word_list = load_word_list()
    if not validate_knowledge_with_wordlist(args.knowledge, word_list):
        return False
    return True

def generate_prompt(args) -> str:
    """生成生产prompt"""
    difficulty_rule = DIFFICULTY_RULES[args.difficulty]
    scene_desc = f"场景要求：{args.scene}" if args.scene else "场景自动匹配知识点"
    return f"""
你是资深K12英语教研专家，严格按照以下要求生成{args.count}道听力三选一图片选择题：
## 难度要求（{args.difficulty}级）
- 句子长度：{difficulty_rule['sentence_length']}
- 干扰项要求：{difficulty_rule['interference']}
- 听力要求：{difficulty_rule['description']}
## 输入参数
- 知识点：{args.knowledge}
- {scene_desc}
## 生产规则
1. 每道题包含1段单句听力文本，3张图片选项（A/B/C），1个正确答案
2. 听力文本自然日常，可使用陈述句、疑问句、祈使句等多种句式，避免生硬
3. 干扰项设置符合难度要求，正确答案唯一
4. 角色从{CHARACTERS}中选择
## 输出格式
严格按照以下格式输出，不要添加任何额外内容：
【题目组描述】
听句子，选出与你听到的内容相符的图片。
---
【题目1】
【听力文本】
[角色]: [符合难度的单句听力内容]
【图片描述】
A: [图片A核心特征描述，与知识点相关]
B: [图片B核心特征描述，干扰项]
C: [图片C核心特征描述，干扰项]
【正确答案】
[正确选项字母A/B/C]
【能力项】
题目1 - 显性事实理解（单句信息点抓取）- [考察核心知识点关键词]
---
【题目2】
...（重复上述结构生成{args.count}道题）
"""

def call_llm(prompt: str) -> str:
    """调用大模型生成内容（实际使用时替换为模型API调用）"""
    print("请输入模型生成的内容：")
    return sys.stdin.read()

def validate_output(output: str, question_count: int) -> bool:
    """校验输出格式合法性"""
    # 检查必填字段
    if "【题目组描述】" not in output:
        print("错误：缺少题目组描述", file=sys.stderr)
        return False
    # 检查题目数量
    question_pattern = r"【题目\d+】"
    questions = re.findall(question_pattern, output)
    if len(questions) != question_count:
        print(f"错误：题目数量不符，预期{question_count}道，实际{len(questions)}道", file=sys.stderr)
        return False
    # 检查每道题的必填字段
    for i in range(1, question_count + 1):
        question_section = re.search(rf"【题目{i}】.*?(?=【题目{i+1}】|---|\Z)", output, re.DOTALL)
        if not question_section:
            print(f"错误：题目{i}格式不完整", file=sys.stderr)
            return False
        section_content = question_section.group(0)
        required_fields = ["【听力文本】", "【图片描述】", "【正确答案】", "【能力项】"]
        for field in required_fields:
            if field not in section_content:
                print(f"错误：题目{i}缺少必填字段{field}", file=sys.stderr)
                return False
        # 校验能力项格式
        ability_match = re.search(r"【能力项】\s*题目\d+ - 显性事实理解（单句信息点抓取）- .*", section_content)
        if not ability_match:
            print(f"错误：题目{i}能力项格式不正确", file=sys.stderr)
            return False
        # 校验答案格式
        answer_match = re.search(r"【正确答案】\s*[ABC]", section_content)
        if not answer_match:
            print(f"错误：题目{i}答案格式不正确，必须为A/B/C", file=sys.stderr)
            return False
    return True

def main():
    args = parse_args()
    if not validate_input(args):
        sys.exit(1)
    prompt = generate_prompt(args)
    output = call_llm(prompt)
    if validate_output(output, args.count):
        print(output)
        sys.exit(0)
    else:
        sys.exit(1)

if __name__ == "__main__":
    main()
