# -*- coding: utf-8 -*-
import requests
import time
import json
import os


# ==================== 类别定义 ====================
categories = [
    {"name": "结婚登记与条件", "desc": "涉及结婚年龄、自愿原则、禁止近亲结婚、疾病限制、登记程序及法律效力等。"},
    {"name": "夫妻权利义务", "desc": "涵盖共同财产管理、相互扶养义务、姓名权、生育权及日常家事代理权等。"},
    {"name": "离婚程序与条件", "desc": "包括协议离婚冷静期、诉讼离婚标准、分居认定、感情破裂证明及调解程序等。"},
    {"name": "财产分割", "desc": "涉及共同财产界定、个人财产保护、债务承担、房产分割规则及隐匿财产追责等。"},
    {"name": "子女抚养与监护权", "desc": "包含抚养费计算标准、探视权实施、非婚生子女权益、抚养关系变更及教育责任等。"},
    {"name": "家庭暴力与保护令", "desc": "涵盖暴力行为认定、人身保护令申请、证据收集、紧急庇护措施及刑事责任关联等。"},
    {"name": "继承权与婚姻关系", "desc": "涉及配偶继承顺位、遗嘱效力、遗产分割冲突、再婚继承权及代位继承问题等。"},
    {"name": "无效婚姻与可撤销婚姻", "desc": "包括重婚无效、胁迫婚姻撤销、隐瞒疾病撤销的程序及法律后果等。"},
    {"name": "涉外婚姻", "desc": "涉及跨国婚姻登记、域外结婚效力认定、财产跨境分割及国际子女抚养公约适用等。"},
    {"name": "法律责任与救济措施", "desc": "包含虚假登记处罚、拒不执行判决后果、损害赔偿计算及强制执行程序等。"}
]

# 构建类别说明文本
CATEGORY_LIST_TEXT = "\n".join([f'{c["name"]}：{c["desc"]}' for c in categories])

# 提示词模板（{category} 会被替换为实际问题所属的类别名）
PROMPT_TEMPLATE = (
    "你是一位婚姻法方面的专家，如果要把【输入文本】分类到【特定类别】中，"
    "那么【输入文本】属于{category}是否准确？给出一个准确性评分，"
    "该评分是0到9之间的正整数，其中0表示完全错误，9表示非常准确。"
    "【输入文本】中的每一行是一条独立数据，需要单独判定。"
    "输出时每条数据的结果单独输出一行，"
    "只允许输出准确性评分，不允许输出其他任何字符。\n\n"
    "【特定类别】\n"
    '["结婚登记与条件","夫妻权利义务","离婚程序与条件","财产分割",'
    '"子女抚养与监护权","家庭暴力与保护令","继承权与婚姻关系",'
    '"无效婚姻与可撤销婚姻","涉外婚姻","法律责任与救济措施"]\n'
    "各类别详细说明如下：\n"
    "{category_list}\n\n"
    "【输入文本】\n"
    "{input_text}"
)

# 每批处理数量
BATCH_SIZE = 20


# ==================== API 调用 ====================
def callServer(prompt, model="Qwen/Qwen2.5-72B-Instruct"):
    """批量调用，返回多行评分文本"""
    url = "https://api.siliconflow.cn/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer sk-cgteigkshpgccdbsfzefmvdjpaicjmydidliorsnjorbqclg",
        "Content-Type": "application/json"
    }
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": prompt}],
        "temperature": 0.2,
        "max_tokens": 200
    }

    success = True
    msg = "OK"
    result = ""
    try:
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()
        result = response.json()['choices'][0]['message']['content']
    except Exception as e:
        success = False
        msg = "API调用异常:" + str(e)
    return success, msg, result


def callServerSingle(prompt, model="Qwen/Qwen2.5-72B-Instruct"):
    """单条调用，返回单个整数评分"""
    url = "https://api.siliconflow.cn/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer sk-cgteigkshpgccdbsfzefmvdjpaicjmydidliorsnjorbqclg",
        "Content-Type": "application/json"
    }
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": prompt}],
        "temperature": 0.2,
        "max_tokens": 10
    }

    success = True
    msg = "OK"
    score = -1
    try:
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()
        content = response.json()['choices'][0]['message']['content'].strip()
        score = int(content)
    except Exception as e:
        success = False
        msg = "API调用异常:" + str(e)
    return success, msg, score


# ==================== 评分解析 ====================
def parseScores(result, expectedCount):
    """解析模型返回的多行评分，每行一个0-9的整数"""
    scores = []
    lines = result.strip().split('\n')
    for line in lines:
        line = line.strip()
        if len(line) == 0:
            continue
        try:
            score = int(line)
            if 0 <= score <= 9:
                scores.append(score)
            else:
                scores.append(-1)
        except ValueError:
            scores.append(-1)
    return scores


# ==================== 单条打分提示词构造 ====================
def buildSinglePrompt(instruction, category):
    """构造单条打分的提示词（批量解析失败时的回退方案）"""
    return (
        "你是一位婚姻法方面的专家，如果要把【输入文本】分类到【特定类别】中，"
        "那么【输入文本】属于" + category + "是否准确？给出一个准确性评分，"
        "该评分是0到9之间的正整数，其中0表示完全错误，9表示非常准确。"
        "只允许输出准确性评分，不允许输出其他任何字符。\n\n"
        "【特定类别】\n"
        '["结婚登记与条件","夫妻权利义务","离婚程序与条件","财产分割",'
        '"子女抚养与监护权","家庭暴力与保护令","继承权与婚姻关系",'
        '"无效婚姻与可撤销婚姻","涉外婚姻","法律责任与救济措施"]\n'
        "各类别详细说明如下：\n"
        + CATEGORY_LIST_TEXT + "\n\n"
        "【输入文本】\n"
        + instruction
    )


# ==================== 主流程 ====================
def scoreQuestions(targetFile):
    # ---------- 读取全部记录 ----------
    records = []
    with open(targetFile, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if line:
                records.append(json.loads(line))
    print(f"共读取 {len(records)} 条记录")

    # ---------- 按类别分组 ----------
    byCategory = {}
    for i, rec in enumerate(records):
        cate = rec.get("category", "")
        if cate not in byCategory:
            byCategory[cate] = []
        byCategory[cate].append(i)

    # ---------- 逐类别处理 ----------
    for cate, indices in byCategory.items():
        # 过滤已打分的记录（断点续传）
        pending = [i for i in indices if "questionScore" not in records[i]]
        if not pending:
            print(f"类别[{cate}] 全部已打分，跳过")
            continue

        print(f"\n{'='*60}")
        print(f"类别[{cate}]: 待打分 {len(pending)} 条")
        print(f"{'='*60}")

        # ---------- 分批处理 ----------
        for batchStart in range(0, len(pending), BATCH_SIZE):
            batchIndices = pending[batchStart:batchStart + BATCH_SIZE]
            batchQuestions = [records[i]["instruction"] for i in batchIndices]
            inputText = "\n".join(batchQuestions)

            prompt = PROMPT_TEMPLATE.format(
                category=cate,
                category_list=CATEGORY_LIST_TEXT,
                input_text=inputText
            )

            batchNum = batchStart // BATCH_SIZE + 1
            totalBatches = (len(pending) + BATCH_SIZE - 1) // BATCH_SIZE
            print(f"\n  批次 {batchNum}/{totalBatches} ({len(batchQuestions)} 条)")

            # ---------- 重试机制 ----------
            scores = None
            for attempt in range(3):
                success, msg, result = callServer(prompt)
                if success:
                    scores = parseScores(result, len(batchQuestions))
                    if len(scores) == len(batchQuestions):
                        print(f"    批量打分成功: {scores}")
                        break
                    else:
                        print(f"    评分数量不匹配(期望{len(batchQuestions)}, 实际{len(scores)}), "
                              f"第{attempt+1}次重试...")
                        scores = None
                else:
                    print(f"    API调用失败(第{attempt+1}次): {msg}")
                time.sleep(2)

            # ---------- 批量失败则回退逐条打分 ----------
            if scores is None:
                print(f"    批量打分失败，回退为逐条打分...")
                scores = []
                for j, idx in enumerate(batchIndices):
                    instruction = records[idx]["instruction"]
                    singlePrompt = buildSinglePrompt(instruction, cate)

                    singleScore = -1
                    for attempt in range(3):
                        success, msg, singleScore = callServerSingle(singlePrompt)
                        if success and 0 <= singleScore <= 9:
                            break
                        print(f"      单条打分失败(第{attempt+1}次): {msg}")
                        time.sleep(2)

                    scores.append(singleScore)
                    print(f"      [{j + 1}/{len(batchIndices)}] score={singleScore}")
                    time.sleep(0.5)

            # ---------- 写入评分并增量保存 ----------
            for j, idx in enumerate(batchIndices):
                records[idx]["questionScore"] = scores[j]

            with open(targetFile, 'w', encoding='utf-8') as f:
                for rec in records:
                    f.write(json.dumps(rec, ensure_ascii=False) + '\n')
            print(f"    已保存到文件")

            time.sleep(1)

    # ---------- 最终统计 ----------
    scored = sum(1 for r in records if "questionScore" in r)
    print(f"\n{'='*60}")
    print(f"打分完成: {scored}/{len(records)} 条已打分")

    # 按类别统计平均分
    print(f"\n各类别评分统计:")
    for cate, indices in byCategory.items():
        cateScores = [records[i].get("questionScore", -1) for i in indices]
        validScores = [s for s in cateScores if s >= 0]
        if validScores:
            avg = sum(validScores) / len(validScores)
            print(f"  {cate}: 平均分={avg:.1f}, 数量={len(validScores)}/{len(indices)}")
        else:
            print(f"  {cate}: 无有效评分")


if __name__ == "__main__":
    targetFile = "../data/testDataTemp/queryData.jsonl"
    scoreQuestions(targetFile)
