"""Tests de l'agrégation des minifigs par personnage."""

from pathlib import Path

from lib.rebrickable.minifig_characters import (
    aggregate_by_character,
    aggregate_by_gender,
    aggregate_character_spans,
    aggregate_presence_by_year,
    load_sets_enriched,
    write_character_counts,
    write_gender_counts,
)


def test_aggregate_by_character_counts_unique_figs() -> None:
    """Compter les minifigs distinctes par personnage en excluant les noms vides."""
    aggregates = aggregate_by_character(
        [
            {
                "set_num": "123-1",
                "part_num": "head-a",
                "known_character": "Owen Grady",
                "fig_num": "fig-owen-1",
                "gender": "male",
            },
            {
                "set_num": "124-1",
                "part_num": "head-b",
                "known_character": "Owen Grady",
                "fig_num": "fig-owen-1",
                "gender": "male",
            },
            {
                "set_num": "125-1",
                "part_num": "head-c",
                "known_character": "Owen Grady",
                "fig_num": "fig-owen-2",
                "gender": "male",
            },
            {
                "set_num": "126-1",
                "part_num": "head-d",
                "known_character": "Figurant",
                "fig_num": "fig-guard-1",
                "gender": "unknown",
            },
            {
                "set_num": "128-1",
                "part_num": "head-f",
                "known_character": "Figurant",
                "fig_num": "fig-guard-1",
                "gender": "unknown",
            },
            {
                "set_num": "129-1",
                "part_num": "head-g",
                "known_character": "",
                "fig_num": "fig-guard-2",
                "gender": "unknown",
            },
        ]
    )

    assert aggregates == [
        {"known_character": "Owen Grady", "gender": "male", "minifig_count": 2},
        {"known_character": "Figurant", "gender": "unknown", "minifig_count": 1},
    ]


def test_aggregate_by_gender_counts_unique_figs() -> None:
    """Compter les minifigs distinctes par genre."""
    aggregates = aggregate_by_gender(
        [
            {"fig_num": "fig-a", "gender": "male"},
            {"fig_num": "fig-a", "gender": "male"},
            {"fig_num": "fig-b", "gender": "female"},
            {"fig_num": "fig-c", "gender": ""},
        ]
    )

    assert aggregates == [
        {"gender": "female", "minifig_count": "1"},
        {"gender": "male", "minifig_count": "1"},
        {"gender": "unknown", "minifig_count": "1"},
    ]


def test_write_character_counts_outputs_csv(tmp_path: Path) -> None:
    """Écrit le CSV des comptes par personnage."""
    destination = tmp_path / "counts.csv"
    rows = [
        {"known_character": "A", "gender": "male", "minifig_count": 2},
        {"known_character": "B", "gender": "female", "minifig_count": 1},
    ]

    write_character_counts(destination, rows)

    assert destination.read_text() == "known_character,gender,minifig_count\nA,male,2\nB,female,1\n"


def test_write_gender_counts_outputs_csv(tmp_path: Path) -> None:
    """Écrit le CSV des comptes par genre."""
    destination = tmp_path / "gender_counts.csv"
    rows = [
        {"gender": "male", "minifig_count": "2"},
        {"gender": "female", "minifig_count": "1"},
    ]

    write_gender_counts(destination, rows)

    assert destination.read_text() == "gender,minifig_count\nmale,2\nfemale,1\n"


def test_aggregate_presence_by_year_excludes_figurants(tmp_path: Path) -> None:
    """Calcule le total annuel en excluant les figurants."""
    sets_path = tmp_path / "sets_enriched.csv"
    sets_path.write_text(
        "set_num,year\n"
        "123-1,2020\n"
        "124-1,2021\n"
    )
    minifigs_rows = [
        {
            "set_num": "123-1",
            "known_character": "Owen Grady",
            "fig_num": "fig-owen",
            "part_num": "head-a",
            "gender": "male",
        },
        {
            "set_num": "124-1",
            "known_character": "Figurant",
            "fig_num": "fig-guard",
            "part_num": "head-b",
            "gender": "unknown",
        },
    ]
    sets_years = load_sets_enriched(sets_path)

    presence = aggregate_presence_by_year(minifigs_rows, sets_years, excluded_characters=["Figurant"])

    assert presence == [
        {"known_character": "Owen Grady", "year": "2020", "minifig_count": "1"},
        {"known_character": "Owen Grady", "year": "2021", "minifig_count": "0"},
    ]


def test_aggregate_character_spans_excludes_figurants(tmp_path: Path) -> None:
    """Calcule les bornes min/max par personnage."""
    sets_path = tmp_path / "sets_enriched.csv"
    sets_path.write_text(
        "set_num,year\n"
        "123-1,2020\n"
        "124-1,2021\n"
        "125-1,2022\n"
    )
    sets_years = load_sets_enriched(sets_path)
    minifigs_rows = [
        {
            "set_num": "123-1",
            "known_character": "Owen Grady",
            "fig_num": "fig-owen",
            "part_num": "head-a",
            "gender": "male",
        },
        {
            "set_num": "124-1",
            "known_character": "Owen Grady",
            "fig_num": "fig-owen",
            "part_num": "head-a",
            "gender": "male",
        },
        {
            "set_num": "125-1",
            "known_character": "Figurant",
            "fig_num": "fig-guard",
            "part_num": "head-b",
            "gender": "unknown",
        },
    ]

    spans = aggregate_character_spans(minifigs_rows, sets_years, excluded_characters=["Figurant"])

    assert spans == [
        {"known_character": "Owen Grady", "start_year": "2020", "end_year": "2021", "total_minifigs": "2", "gender": "male"},
    ]
