"""
演示业务层：组织题目、三种模式运行与结果序列化。

终端 main.py 与 Web web_app.py 共用此模块，避免逻辑重复。
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Callable, Iterator

from analysis import extract_final_answer, has_reasoning_steps, is_answer_correct
from config import API_KEY, MODEL_NAME, SEED, TEMPERATURE
from demo import ModeResult, run_direct, run_few_shot_cot, run_zero_shot_cot
from questions import DEMO_QUESTIONS, DemoQuestion

ROLE_LABELS = {
    "system": "system（系统角色）",
    "user": "user（用户角色）",
    "assistant": "assistant（示例回答）",
}


@dataclass(frozen=True)
class ModeSpec:
    id: str
    title: str
    subtitle: str
    badge: str
    runner: Callable[[DemoQuestion], ModeResult]


MODES: list[ModeSpec] = [
    ModeSpec("direct", "模式 A", "无 CoT", "直接要答案", run_direct),
    ModeSpec("zero_shot", "模式 B", "零样本 CoT", "分步思考·无示例", run_zero_shot_cot),
    ModeSpec("few_shot", "模式 C", "少样本 CoT", "示例推理链", run_few_shot_cot),
]


def check_api_key() -> None:
    if not API_KEY:
        raise RuntimeError(
            "未读取到系统环境变量 DASHSCOPE_API_KEY，"
            "请在 Windows 系统环境变量中配置后重新打开终端。"
        )


def question_to_dict(index: int) -> dict[str, Any]:
    q = DEMO_QUESTIONS[index - 1]
    return {
        "index": index,
        "title": q.title,
        "question": q.question,
        "expected_answer": q.expected_answer,
        "why_hard": q.why_hard,
    }


def list_questions() -> list[dict[str, Any]]:
    return [question_to_dict(i) for i in range(1, len(DEMO_QUESTIONS) + 1)]


def mode_result_to_dict(mode: ModeSpec, result: ModeResult, question: DemoQuestion) -> dict[str, Any]:
    final_answer = extract_final_answer(result.reply)
    correct = is_answer_correct(final_answer, question.expected_answer)
    stepped = has_reasoning_steps(result.reply)
    messages = [
        {
            "index": i,
            "role": msg["role"],
            "role_label": ROLE_LABELS.get(msg["role"], msg["role"]),
            "content": msg["content"],
        }
        for i, msg in enumerate(result.messages, start=1)
    ]
    return {
        "id": mode.id,
        "title": mode.title,
        "subtitle": mode.subtitle,
        "badge": mode.badge,
        "prompt_summary": result.prompt_summary,
        "message_count": len(result.messages),
        "messages": messages,
        "reply": result.reply,
        "final_answer": final_answer,
        "correct": correct,
        "has_steps": stepped,
    }


def get_runtime_info() -> dict[str, Any]:
    masked = "未配置"
    if API_KEY:
        masked = f"{API_KEY[:4]}...{API_KEY[-4:]}" if len(API_KEY) > 8 else "已配置"
    return {
        "model": MODEL_NAME,
        "temperature": TEMPERATURE,
        "seed": SEED,
        "api_key_status": masked,
        "api_configured": bool(API_KEY),
        "call_path": "dashscope.Generation.call() → 阿里云百炼（真实 API，消耗 Token）",
    }


def run_question_events(question_index: int) -> Iterator[dict[str, Any]]:
    """按步骤产出事件，供 Web SSE 流式展示运行过程。"""
    check_api_key()
    question = DEMO_QUESTIONS[question_index - 1]

    yield {
        "type": "init",
        "runtime": get_runtime_info(),
        "question": question_to_dict(question_index),
        "mode_count": len(MODES),
    }

    results: list[dict[str, Any]] = []

    for step, mode in enumerate(MODES, start=1):
        yield {
            "type": "mode_start",
            "step": step,
            "total": len(MODES),
            "mode_id": mode.id,
            "title": mode.title,
            "subtitle": mode.subtitle,
        }

        result = mode.runner(question)
        payload = mode_result_to_dict(mode, result, question)
        results.append(payload)

        yield {
            "type": "mode_done",
            "step": step,
            "total": len(MODES),
            "result": payload,
        }

    yield {
        "type": "summary",
        "prompt_diff": [
            {
                "title": r["title"],
                "message_count": r["message_count"],
                "prompt_summary": r["prompt_summary"],
            }
            for r in results
        ],
        "result_diff": [
            {
                "title": r["title"],
                "final_answer": r["final_answer"],
                "correct": r["correct"],
                "has_steps": r["has_steps"],
            }
            for r in results
        ],
        "results": results,
    }

    yield {"type": "done", "api_calls": len(MODES)}


def run_question_sync(question_index: int) -> dict[str, Any]:
    """一次性返回完整结果（非流式备用接口）。"""
    final: dict[str, Any] = {}
    for event in run_question_events(question_index):
        if event["type"] == "init":
            final["runtime"] = event["runtime"]
            final["question"] = event["question"]
        elif event["type"] == "summary":
            final["summary"] = event
            final["results"] = event["results"]
        elif event["type"] == "done":
            final["api_calls"] = event["api_calls"]
    return final
