"""Tests for the GIAS code->name dictionaries (spec 2026-07-09).

The dictionaries are generated from the live GIAS bulk CSV by
pipeline/scripts/generate_gias_codes.py — these tests assert the module's
contract, key sentinel values the marts/UI depend on, and that the pipeline
copy has not drifted from the canonical backend module.
"""

import math
from pathlib import Path

from backend.gias_codes import (
    ADMISSIONS_POLICY,
    ESTABLISHMENT_STATUS,
    OFFICIAL_SIXTH_FORM,
    PHASE_OF_EDUCATION,
    RELIGIOUS_CHARACTER,
    SCHOOL_TYPE,
    translate,
)

REPO = Path(__file__).resolve().parents[2]


def test_translate_known_code():
    open_code = next(c for c, n in ESTABLISHMENT_STATUS.items() if n == "Open")
    assert translate(open_code, ESTABLISHMENT_STATUS) == "Open"


def test_translate_unknown_code_degrades_gracefully():
    assert translate(9999, ESTABLISHMENT_STATUS) == "Unknown (9999)"


def test_translate_none_and_nan_return_none():
    assert translate(None, ESTABLISHMENT_STATUS) is None
    assert translate(float("nan"), ESTABLISHMENT_STATUS) is None


def test_translate_accepts_float_codes():
    # pd.read_sql yields float columns when NULLs are present
    open_code = next(c for c, n in ESTABLISHMENT_STATUS.items() if n == "Open")
    assert translate(float(open_code), ESTABLISHMENT_STATUS) == "Open"


def test_sentinel_names_present():
    """Names the marts/UI compare against must exist verbatim."""
    assert "Open" in ESTABLISHMENT_STATUS.values()
    assert "Open, but proposed to close" in ESTABLISHMENT_STATUS.values()
    assert "Has a sixth form" in OFFICIAL_SIXTH_FORM.values()
    assert "Primary" in PHASE_OF_EDUCATION.values()
    assert "Secondary" in PHASE_OF_EDUCATION.values()
    assert "Does not apply" in RELIGIOUS_CHARACTER.values()
    assert all(len(d) > 0 for d in (
        SCHOOL_TYPE, ESTABLISHMENT_STATUS, PHASE_OF_EDUCATION,
        OFFICIAL_SIXTH_FORM, RELIGIOUS_CHARACTER, ADMISSIONS_POLICY,
    ))


def test_pipeline_copy_is_identical():
    canonical = (REPO / "backend" / "gias_codes.py").read_text()
    copy = (REPO / "pipeline" / "scripts" / "gias_codes.py").read_text()
    assert canonical == copy, (
        "pipeline/scripts/gias_codes.py has drifted from backend/gias_codes.py — "
        "regenerate with pipeline/scripts/generate_gias_codes.py and copy the file"
    )


def test_seed_matches_dictionaries():
    import csv
    fields = {
        "school_type": SCHOOL_TYPE,
        "establishment_status": ESTABLISHMENT_STATUS,
        "phase_of_education": PHASE_OF_EDUCATION,
        "official_sixth_form": OFFICIAL_SIXTH_FORM,
        "religious_character": RELIGIOUS_CHARACTER,
        "admissions_policy": ADMISSIONS_POLICY,
    }
    seed_path = REPO / "pipeline" / "transform" / "seeds" / "gias_code_names.csv"
    seed: dict[str, dict[int, str]] = {k: {} for k in fields}
    with open(seed_path, newline="") as fh:
        for row in csv.DictReader(fh):
            seed[row["field"]][int(row["code"])] = row["name"]
    assert seed == fields


def test_blank_name_sentinel_codes_map_to_empty_string():
    """GIAS carries codes whose (name) column is blank — e.g. ReligiousCharacter
    99 (~4k schools) and AdmissionsPolicy 9 (~5.6k schools). The old name
    pipeline served these as empty strings; the dictionaries must reproduce
    that ("" is falsy, so UI tag heuristics stay silent) rather than letting
    them hit the "Unknown (<code>)" path meant for genuinely new codes."""
    assert RELIGIOUS_CHARACTER[99] == ""
    assert ADMISSIONS_POLICY[9] == ""
    assert translate(99, RELIGIOUS_CHARACTER) == ""
    assert translate(9, ADMISSIONS_POLICY) == ""
