"""
终端输出模块。

负责把演示过程打印得清晰易读，包括：
- 项目是否真实调用 API 的说明
- 各文件分工与运行流程
- 每道题三种模式的对比结果
"""

import sys
import textwrap

from config import API_KEY, MODEL_NAME, SEED, TEMPERATURE

ROLE_LABELS = {
    "system": "system（系统角色：设定行为规则）",
    "user": "user（用户角色：本次提问）",
    "assistant": "assistant（助手角色：示例回答，供模型模仿）",
}


def _configure_stdout() -> None:
    """尽量让 Windows 终端正确显示中文。"""
    if hasattr(sys.stdout, "reconfigure"):
        try:
            sys.stdout.reconfigure(encoding="utf-8")
        except Exception:
            pass


_configure_stdout()


def print_banner(title: str) -> None:
    line = "=" * 60
    print(f"\n{line}\n  {title}\n{line}")


def print_section(title: str) -> None:
    print(f"\n{'-' * 60}\n>> {title}\n{'-' * 60}")


def print_kv(label: str, value: str, indent: int = 0) -> None:
    prefix = " " * indent
    print(f"{prefix}{label}")
    wrapped = textwrap.indent(textwrap.fill(value, width=72), "  ")
    print(wrapped)


def print_model_reply(reply: str) -> None:
    print("\n【模型回复】")
    print(textwrap.indent(reply, "  "))


def print_messages(messages: list[dict[str, str]], summary: str = "") -> None:
    """打印本次发送给模型的完整 messages，便于对比三种模式的提示词差异。"""
    print("\n【发送给模型的提示词】")
    if summary:
        print(f"  结构说明：{summary}")
    print(f"  共 {len(messages)} 条消息：")
    for i, msg in enumerate(messages, start=1):
        role = msg["role"]
        label = ROLE_LABELS.get(role, role)
        content = msg["content"].strip()
        print(f"\n  --- 消息 {i} · {label} ---")
        print(textwrap.indent(content, "    "))


def _mask_api_key(key: str | None) -> str:
    if not key:
        return "未配置"
    if len(key) <= 8:
        return "已配置（长度较短，已隐藏）"
    return f"已配置（{key[:4]}...{key[-4:]}）"


def print_runtime_info() -> None:
    """启动时打印运行环境与真实性说明。"""
    print_section("运行环境（真实 API 调用，非模拟）")
    print_kv("调用方式", "dashscope.Generation.call() → 阿里云百炼云端")
    print_kv("模型", MODEL_NAME)
    print_kv("API Key", _mask_api_key(API_KEY))
    print_kv("参数", f"temperature={TEMPERATURE}, seed={SEED}")
    print_kv(
        "是否真实运行",
        "是。每次「模型回复」都是实时请求百炼接口返回的结果，"
        "会消耗 Token；断网或 Key 无效时会直接报错，没有写死的假答案。",
    )


def print_project_structure() -> None:
    """打印项目构建方式，帮助学生理解代码分工。"""
    print_section("项目是怎么构建的")
    lines = [
        "main.py       入口：组织演示流程，打印对比小结",
        "demo.py       核心：三种模式组装 messages 并调用模型",
        "prompts.py    提示词：无CoT / 零样本CoT / 少样本CoT 模板（改效果主要改这里）",
        "questions.py  题库：3 道经典演示题",
        "llm_client.py API层：唯一真正联网发请求的地方",
        "config.py     配置：从 os.getenv 读取 DASHSCOPE_API_KEY",
    ]
    for line in lines:
        print(f"  {line}")


def print_run_flow() -> None:
    """打印单道题的执行步骤。"""
    print_section("单道题运行流程（每题调用 3 次百炼 API）")
    steps = [
        "1. main.py 从 questions.py 取出题目",
        "2. 模式 A：prompts.py(无CoT) → demo.py 拼 messages → llm_client.py 发请求",
        "3. 模式 B：prompts.py(零样本CoT) → demo.py 拼 messages → llm_client.py 发请求",
        "4. 模式 C：prompts.py(少样本CoT+示例) → demo.py 拼 messages → llm_client.py 发请求",
        "5. main.py 提取「最终答案」，判断正确性与是否有分步推理",
        "6. 打印 A/B/C 对比小结",
    ]
    for step in steps:
        print(f"  {step}")


def print_intro() -> None:
    print_banner("CoT 思维链（Chain-of-Thought）教学演示")
    print(
        textwrap.fill(
            "CoT 的核心：不要急着给最终答案，先让模型把中间推理步骤写出来。"
            "这样复杂题更不容易跳步出错，推理过程也便于检查和纠错。",
            width=72,
        )
    )
    print("\n本演示对比三种写法：")
    print("  1) 无 CoT      → 直接要答案（容易跳步）")
    print("  2) 零样本 CoT  → 不给示例，只要求分步思考")
    print("  3) 少样本 CoT  → 给一个带推理过程的示例，再让模型模仿")
    print_runtime_info()
    print_project_structure()
    print_run_flow()
    print("\n网页版演示：python web_app.py  →  http://127.0.0.1:8765")
    print("详细说明见：docs/项目说明.md")
