"""Report generation: radar chart, markdown, and JSON."""

import json
from datetime import datetime
from pathlib import Path
from typing import Dict

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import numpy as np

from .models import CheckupResult
from .rules import DIMENSIONS

# Chinese font setup
_CN_FONT = None
for _name in ["Arial Unicode MS", "PingFang SC", "Heiti SC", "STHeiti", "SimHei"]:
    if any(_name in f.name for f in fm.fontManager.ttflist):
        _CN_FONT = _name
        break
if _CN_FONT:
    plt.rcParams["font.sans-serif"] = [_CN_FONT, "Arial"]
plt.rcParams["axes.unicode_minus"] = False

# Dimension order for radar chart
DIM_ORDER = ["questioning", "judgment", "hands_on", "deep_thinking", "execution", "narrative"]


def generate_all(result: CheckupResult, output_dir: Path):
    """Generate all report outputs."""
    output_dir.mkdir(parents=True, exist_ok=True)

    generate_radar(result, output_dir)
    generate_markdown(result, output_dir)
    generate_json(result, output_dir)


def generate_radar(result: CheckupResult, output_dir: Path):
    """Generate six-dimension radar chart."""
    names = [result.dimensions[k].name for k in DIM_ORDER]
    scores = [result.dimensions[k].score for k in DIM_ORDER]
    colors = [DIMENSIONS[k]["color"] for k in DIM_ORDER]

    # Radar chart
    fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(polar=True))
    angles = np.linspace(0, 2 * np.pi, len(names), endpoint=False).tolist()

    # Close the polygon
    plot_scores = [s / 100 for s in scores] + [scores[0] / 100]
    plot_angles = angles + [angles[0]]

    ax.plot(plot_angles, plot_scores, "o-", linewidth=2, color="#2C3E50")
    ax.fill(plot_angles, plot_scores, alpha=0.15, color="#3498DB")

    # Annotate each vertex
    for i, (angle, score, name) in enumerate(zip(angles, scores, names)):
        color = colors[i]
        ax.plot(angle, score / 100, "o", markersize=10, color=color)
        va = "bottom" if score > 30 else "top"
        ax.annotate(
            f"{name}\n{score:.0f}",
            xy=(angle, score / 100),
            fontsize=11,
            fontweight="bold",
            ha="center",
            va=va,
            color=color,
        )

    ax.set_ylim(0, 1)
    ax.set_yticklabels([])
    ax.set_xticks(angles)
    ax.set_xticklabels([""] * len(names))
    ax.set_title("AI Checkup · 六维能力快照", fontsize=16, fontweight="bold", pad=20)

    fig.savefig(output_dir / "radar.png", dpi=150, bbox_inches="tight")
    plt.close(fig)


def generate_markdown(result: CheckupResult, output_dir: Path):
    """Generate markdown report."""
    d = result.dimensions
    lines = [
        "# AI Checkup 六维能力分析报告",
        "",
        f"**数据范围**: {result.period} ({len(result.weeks)} 周)",
        f"**会话总数**: {result.total_conversations}",
        f"**数据来源**: {result.platform or '未知'}",
        f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
        "",
        "---",
        "",
        "## 整体快照",
        "",
    ]

    for key in DIM_ORDER:
        dim = d[key]
        filled = int(dim.score / 5)
        bar = "█" * filled + "░" * (20 - filled)
        lines.append(f"- **{dim.name}** ({dim.name_en}) {bar} {dim.score:.0f}/100")

    # Strong signals
    lines += ["", "---", "", "## 强信号分析", ""]

    # 1. Questioning
    lines.append("### 1. 提问力 (Questioning)")
    q_dist = result.raw_analysis.get("question_distribution", {})
    total_q = sum(q_dist.values()) if q_dist else 0
    if total_q > 0:
        lines.append(f"- 总计 {total_q} 次提问")
        for level in ["L4_Meta", "L3_Why", "L2_What", "L1_How"]:
            c = q_dist.get(level, 0)
            pct = c / total_q * 100
            lines.append(f"  - {level}: {c} ({pct:.0f}%)")
    _add_trend(lines, d["questioning"].weekly_data)
    lines.append("")

    # 2. Judgment
    lines.append("### 2. 判断力 (Judgment)")
    lines.append(f"- 含判断信号的会话平均占比: {d['judgment'].raw_value:.0%}")
    j_types = result.raw_analysis.get("judgment_types", {})
    labels_map = {
        "direction_setting": "方向设定",
        "evaluation": "评价比较",
        "rejection": "否定修正",
        "uncertainty_tolerance": "不确定性容忍",
    }
    for jt, count in sorted(j_types.items(), key=lambda x: -x[1]):
        lines.append(f"  - {labels_map.get(jt, jt)}: {count} 次")
    _add_trend(lines, d["judgment"].weekly_data)
    lines.append("")

    # 3. Hands-on
    lines.append("### 3. 动手力 (Hands-on)")
    lines.append(f"- 输出型会话平均占比: {d['hands_on'].raw_value:.0%}")
    _add_trend(lines, d["hands_on"].weekly_data)
    lines.append("")

    # Weak signals
    lines += ["---", "", "## 弱信号参考", ""]

    lines.append("### 4. 深思力 (Deep Thinking)")
    lines.append(f"- L3思维+反思型会话平均占比: {d['deep_thinking'].raw_value:.0%}")
    lines.append("")

    lines.append("### 5. 践行力 (Execution)")
    lines.append(f"- 每周平均活跃天数: {d['execution'].raw_value:.1f} 天")
    lines.append("")

    lines.append("### 6. 叙事力 (Narrative)")
    lines.append(f"- 写作/叙事型会话平均占比: {d['narrative'].raw_value:.0%}")
    lines.append("")

    # Insights
    lines += ["---", "", "## 关键洞察", ""]
    for insight in result.insights:
        lines.append(f"- {insight}")
    lines.append("")

    with open(output_dir / "report.md", "w", encoding="utf-8") as f:
        f.write("\n".join(lines))


def generate_json(result: CheckupResult, output_dir: Path):
    """Export analysis data as JSON."""
    data = {
        "period": result.period,
        "total_conversations": result.total_conversations,
        "platform": result.platform,
        "dimensions": {},
        "insights": result.insights,
        "raw_analysis": result.raw_analysis,
    }

    for key in DIM_ORDER:
        dim = result.dimensions[key]
        data["dimensions"][key] = {
            "name": dim.name,
            "name_en": dim.name_en,
            "score": dim.score,
            "raw_value": dim.raw_value,
            "weekly_data": dim.weekly_data,
            "description": dim.description,
        }

    with open(output_dir / "data.json", "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)


def _add_trend(lines, weekly_data: Dict[str, float]):
    """Add trend analysis line if enough data."""
    values = list(weekly_data.values())
    if len(values) >= 3:
        mid = len(values) // 2
        early = float(np.mean(values[:mid]))
        late = float(np.mean(values[mid:]))
        if late > early + 0.05:
            trend = "↑ 上升"
        elif late < early - 0.05:
            trend = "↓ 下降"
        else:
            trend = "→ 稳定"
        lines.append(f"- **趋势**: 前半期 {early:.0%} → 后半期 {late:.0%} ({trend})")
