"""Graphique des pièces rares par set."""

from pathlib import Path
from typing import List, Tuple

import matplotlib.pyplot as plt
from matplotlib.patches import Patch

from lib.filesystem import ensure_parent_dir
from lib.rebrickable.stats import read_rows


def load_top_sets(path: Path, limit: int = 15) -> List[dict]:
    """Charge les sets triés par nombre de pièces rares et limite le top."""
    rows = read_rows(path)
    sorted_rows = sorted(
        rows,
        key=lambda row: (
            -int(row["rare_parts_distinct"]),
            -int(row["rare_parts_quantity"]),
            row["set_num"],
        ),
    )
    return sorted_rows[:limit]


def split_counts(rows: List[dict]) -> Tuple[List[int], List[int]]:
    """Sépare les comptages minifig vs hors minifig."""
    non_minifig: List[int] = []
    minifig: List[int] = []
    for row in rows:
        total = int(row["rare_parts_distinct"])
        minifig_count = int(row["rare_minifig_parts_distinct"])
        non_minifig.append(total - minifig_count)
        minifig.append(minifig_count)
    return non_minifig, minifig


def plot_rare_parts_per_set(rare_by_set_path: Path, destination_path: Path) -> None:
    """Trace le top des sets contenant des pièces exclusives."""
    rows = load_top_sets(rare_by_set_path)
    if not rows:
        return
    non_minifig, minifig = split_counts(rows)
    y_positions = list(range(len(rows)))
    labels = [f"{row['set_num']} · {row['name']} ({row['year']})" for row in rows]
    owned_mask = [row["in_collection"] == "true" for row in rows]

    base_color = "#1f77b4"
    accent_color = "#f28e2b"
    fig, ax = plt.subplots(figsize=(11, 8))
    for y, value, is_owned in zip(y_positions, non_minifig, owned_mask):
        alpha = 0.92 if is_owned else 0.45
        ax.barh(y, value, color=base_color, alpha=alpha, label=None)
    for y, value, offset, is_owned in zip(y_positions, minifig, non_minifig, owned_mask):
        alpha = 0.92 if is_owned else 0.45
        ax.barh(y, value, left=offset, color=accent_color, alpha=alpha, label=None)

    ax.set_yticks(y_positions)
    ax.set_yticklabels(labels)
    ax.invert_yaxis()
    ax.set_xlabel("Variantes de pièces exclusives (hors rechanges)")
    ax.set_title("Pièces rares par set (top)")
    ax.grid(axis="x", linestyle="--", alpha=0.35)

    handles = [
        Patch(facecolor=base_color, edgecolor="none", label="Pièces hors minifigs"),
        Patch(facecolor=accent_color, edgecolor="none", label="Pièces de minifigs"),
        Patch(facecolor="#000000", edgecolor="none", alpha=0.92, label="Set possédé"),
        Patch(facecolor="#000000", edgecolor="none", alpha=0.45, label="Set manquant"),
    ]
    ax.legend(handles=handles, loc="lower right", frameon=False)

    ensure_parent_dir(destination_path)
    fig.tight_layout()
    fig.savefig(destination_path, dpi=170)
    plt.close(fig)
