"""Speed-vs-accuracy Pareto scatter and per-method bar charts."""
from __future__ import annotations

from pathlib import Path
from typing import Any, Dict, List

import matplotlib

matplotlib.use("Agg")  # headless
import matplotlib.pyplot as plt  # noqa: E402


def pareto_points(rows: List[Dict[str, Any]], x_key: str, y_key: str) -> List[Dict[str, Any]]:
    points = []
    for row in rows:
        if row.get("status") != "ok":
            continue
        if row.get(x_key) is None or row.get(y_key) is None:
            continue
        points.append({
            "method": row["method"],
            "x": row[x_key],
            "y": row[y_key],
            "t4_deployable": row.get("t4_deployable"),
        })
    return points


def _scatter(points, x_label, y_label, title, out_path: Path) -> None:
    fig, ax = plt.subplots(figsize=(7, 5))
    for p in points:
        marker = "o" if p["t4_deployable"] else "x"
        ax.scatter(p["x"], p["y"], marker=marker, s=80)
        ax.annotate(p["method"], (p["x"], p["y"]), textcoords="offset points", xytext=(5, 5))
    ax.set_xlabel(x_label)
    ax.set_ylabel(y_label)
    ax.set_title(title + "  (o = T4-deployable, x = A100-only)")
    fig.tight_layout()
    fig.savefig(out_path, dpi=120)
    plt.close(fig)


def _bar(rows, metric_key, y_label, out_path: Path) -> None:
    ok = [r for r in rows if r.get("status") == "ok" and r.get(metric_key) is not None]
    fig, ax = plt.subplots(figsize=(7, 5))
    ax.bar([r["method"] for r in ok], [r[metric_key] for r in ok])
    ax.set_ylabel(y_label)
    ax.set_title(metric_key)
    fig.tight_layout()
    fig.savefig(out_path, dpi=120)
    plt.close(fig)


def render_all(rows: List[Dict[str, Any]], out_dir: Path) -> List[Path]:
    out_dir = Path(out_dir)
    out_dir.mkdir(parents=True, exist_ok=True)
    written: List[Path] = []

    p1 = out_dir / "pareto_latency_cer.png"
    _scatter(pareto_points(rows, "mean_latency_s", "mean_cer"),
             "mean latency (s)  [lower=faster]", "CER vs BF16  [lower=better]",
             "Speed vs recognition accuracy", p1)
    written.append(p1)

    p2 = out_dir / "pareto_latency_iou.png"
    _scatter(pareto_points(rows, "mean_latency_s", "mean_bbox_iou"),
             "mean latency (s)  [lower=faster]", "bbox IoU vs BF16  [higher=better]",
             "Speed vs detection accuracy", p2)
    written.append(p2)

    for metric, label in [("mean_latency_s", "mean latency (s)"),
                          ("mean_cer", "CER vs BF16"),
                          ("mean_bbox_iou", "bbox IoU vs BF16")]:
        bp = out_dir / f"bar_{metric}.png"
        _bar(rows, metric, label, bp)
        written.append(bp)

    return written
