# -*- coding: utf-8 -*-
"""Generate PPT assets for stage-3 (PBC) update."""
from __future__ import annotations

import importlib.util
import subprocess
import sys
from pathlib import Path

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np

ROOT = Path(__file__).resolve().parents[1]
OUT = Path(__file__).resolve().parent
SRC_OUT = ROOT / "build" / "Release" / "OutFile"
MAT_OUT = (
    ROOT.parent
    / "三维matlab代码"
    / "matlab 3D一阶基+散射边界条件+单周期边界"
    / "OutFile"
)
MESH = ROOT / "build" / "Release" / "PBCmesh.dat"
PLOT_SCRIPT = ROOT / "tools" / "plot_domain_faces.py"


def _resolve_cpp_outdir() -> Path:
    """Pick C++ OutFile that matches PBCmesh vertex count, else fall back to MATLAB."""
    mesh_spec = importlib.util.spec_from_file_location(
        "validate_pbcmesh", ROOT / "tools" / "validate_and_fix_pbcmesh.py"
    )
    mesh_mod = importlib.util.module_from_spec(mesh_spec)
    mesh_spec.loader.exec_module(mesh_mod)
    plot_spec = importlib.util.spec_from_file_location(
        "plot_domain_faces", PLOT_SCRIPT
    )
    plot_mod = importlib.util.module_from_spec(plot_spec)
    plot_spec.loader.exec_module(plot_mod)

    mesh = mesh_mod.load_mesh_dat(MESH)
    n_vertex = mesh["n_vertex"]

    candidates = [SRC_OUT, ROOT / "build" / "Release" / "OutFile_double"]
    for cand in candidates:
        normE_path = cand / "normE"
        if not normE_path.exists():
            continue
        ne = plot_mod.load_normE(normE_path)
        if ne.size == n_vertex:
            print(f"  [cpp] using {cand} (n={ne.size})")
            return cand

    print(
        f"  [warn] no C++ normE with {n_vertex} vertices; "
        f"re-run: OpticsFEM.exe pbc3d_sbc.json in build/Release"
    )
    print(f"  [warn] C++ panel temporarily uses MATLAB reference at {MAT_OUT}")
    return MAT_OUT


def merge_pbc_faces() -> Path:
    """Plot domain 2 + 5 merged (simulation only, no MATLAB compare)."""
    import shutil

    out = OUT / "pbc_faces_domain2_domain5.png"
    out_src = SRC_OUT / "pbc_faces_domain2_domain5.png"
    cpp_out = _resolve_cpp_outdir()

    cmd = [
        sys.executable,
        str(PLOT_SCRIPT),
        "--mesh",
        str(MESH),
        "--outdir",
        str(cpp_out),
        "--domains",
        "2",
        "5",
        "--combined",
        "--no-compare",
        "--output",
        str(out),
    ]
    subprocess.run(cmd, check=True, cwd=ROOT)
    shutil.copy2(out, out_src)
    return out


plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei", "Arial"]
plt.rcParams["axes.unicode_minus"] = False

BLUE = "#4874CB"
ORANGE = "#EE822F"
GREEN = "#75BD42"
GRAY = "#BFBFBF"
DARK = "#44546A"
LIGHT = "#E7E6E6"


def roadmap_stage_progress() -> Path:
    fig, ax = plt.subplots(figsize=(11, 3.8), facecolor="white")
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 3.8)
    ax.axis("off")

    stages = [
        ("0\n工程基础", True),
        ("1\n本征频率", "partial"),
        ("2\nPEC/ELE", True),
        ("3\nPBC", True),
        ("4\nBELE/源项", False),
        ("5\nPML/Port", False),
        ("6\n本征模式/二阶", False),
    ]
    n = len(stages)
    w = 1.15
    gap = 0.18
    x0 = 0.35

    for i, (label, status) in enumerate(stages):
        x = x0 + i * (w + gap)
        if status is True:
            color, edge = GREEN, "#4A7C3F"
        elif status == "partial":
            color, edge = ORANGE, "#C66A1A"
        else:
            color, edge = GRAY, "#999999"
        ax.add_patch(
            mpatches.FancyBboxPatch(
                (x, 1.5),
                w,
                1.1,
                boxstyle="round,pad=0.06",
                facecolor=color,
                edgecolor=edge,
                alpha=0.92,
            )
        )
        ax.text(x + w / 2, 2.05, label, ha="center", va="center", fontsize=9.5, weight="bold", color="white")
        if i < n - 1:
            ax.annotate(
                "",
                xy=(x + w + gap * 0.15, 2.05),
                xytext=(x + w, 2.05),
                arrowprops=dict(arrowstyle="->", color=DARK, lw=2),
            )

    ax.text(0.35, 0.55, "[完成]", fontsize=10, color=GREEN, weight="bold")
    ax.text(1.5, 0.55, "[部分]", fontsize=10, color=ORANGE, weight="bold")
    ax.text(2.8, 0.55, "[待做]", fontsize=10, color="#888888", weight="bold")
    ax.set_title("OpticsFEM 3D 扩展分阶段进度（当前：阶段 3 完成）", fontsize=13, weight="bold", color=DARK, pad=12)

    out = OUT / "roadmap_stage_progress.png"
    fig.savefig(out, dpi=150, bbox_inches="tight", facecolor="white")
    plt.close(fig)
    return out


def pbc_validation_metrics() -> Path:
    labels = ["矩阵 rel_max", "normE L2 rel", "单PBC |r|", "normE 相关系数"]
    values = [1.1e-6, 1.1e-6, 3.9e-13, 1.0]
    display = ["1.1e-6", "1.1e-6", "3.9e-13", "1.0"]

    fig, ax = plt.subplots(figsize=(8, 4), facecolor="white")
    colors = [BLUE, ORANGE, GREEN, "#30C0B4"]
    bars = ax.bar(labels, values, color=colors, edgecolor=DARK, width=0.55)
    ax.set_yscale("log")
    ax.set_ylabel("数值（对数轴）", fontsize=11)
    ax.set_title("双周期 PBC 验证指标（C++ vs MATLAB）", fontsize=12, weight="bold", color=DARK)
    ax.set_ylim(1e-14, 2)
    for b, txt in zip(bars, display):
        ax.text(b.get_x() + b.get_width() / 2, b.get_height() * 2.5, txt, ha="center", fontsize=10, weight="bold")
    ax.grid(axis="y", alpha=0.3, linestyle="--")
    fig.tight_layout()
    out = OUT / "pbc_validation_metrics.png"
    fig.savefig(out, dpi=150, bbox_inches="tight", facecolor="white")
    plt.close(fig)
    return out


def module_status_stage3() -> Path:
    fig, ax = plt.subplots(figsize=(10, 4.2), facecolor="white")
    ax.axis("off")
    cols = ["模块", "状态", "说明"]
    rows = [
        ["体积分 + SBC", "完成", "FemType=4 散射闭环"],
        ["PEC/ELE（阶段2）", "完成", "Assemble_PEC_ELE，边 DOF 消元"],
        ["PBC 单周期（阶段3）", "完成", "singlePBC_scatter.json"],
        ["PBC 双周期（阶段3）", "完成", "doublePBC_scatter.json，角点合并"],
        ["本征 A/B 矩阵", "完成", "与 MATLAB COO 逐行一致"],
        ["BELE/MAG/SCD", "待做", "阶段 4"],
        [".em 接口", "待做", "Design.em 适配"],
    ]
    table = ax.table(cellText=rows, colLabels=cols, loc="center", cellLoc="center")
    table.auto_set_font_size(False)
    table.set_fontsize(10)
    table.scale(1, 1.55)
    for (r, c), cell in table.get_celld().items():
        if r == 0:
            cell.set_facecolor(BLUE)
            cell.set_text_props(color="white", weight="bold")
        else:
            cell.set_facecolor(LIGHT if r % 2 == 0 else "white")
            if c == 1 and rows[r - 1][1] == "完成":
                cell.set_text_props(color=GREEN, weight="bold")
    ax.set_title("三维拓展模块完成状态（阶段三更新）", fontsize=12, weight="bold", color=DARK, pad=18)
    out = OUT / "module_status_stage3.png"
    fig.savefig(out, dpi=150, bbox_inches="tight", facecolor="white")
    plt.close(fig)
    return out


def main() -> None:
    OUT.mkdir(parents=True, exist_ok=True)
    outputs = [
        merge_pbc_faces(),
        roadmap_stage_progress(),
        pbc_validation_metrics(),
        module_status_stage3(),
    ]
    print("Generated PPT assets:")
    for p in outputs:
        print(f"  {p}")


if __name__ == "__main__":
    main()
