"""_national_averages_payload reads persisted marts (computed at import
time) — it must never aggregate the dataframe. Both marts hold OFFICIAL
DfE figures, so a missing KS4 mart yields an empty secondary series —
never a computed stand-in the UI would mislabel as official."""

import numpy as np
import pandas as pd
import pytest

LATEST = 202425


def _df():
    return pd.DataFrame(
        [
            dict(year=202324, attainment_8_score=40.0, rwm_expected_pct=np.nan),
            dict(year=LATEST, attainment_8_score=50.0, rwm_expected_pct=np.nan),
            dict(year=LATEST, attainment_8_score=30.0, rwm_expected_pct=np.nan),
            dict(year=LATEST, attainment_8_score=np.nan, rwm_expected_pct=80.0),
        ]
    )


class _Ks2Row:
    year = LATEST
    rwm_expected_pct = 62.1
    gps_expected_pct = 72.0
    # Per-subject higher-standard nationals — reading/maths reach the higher
    # standard, writing is teacher-assessed at greater depth (writing_gd_pct).
    reading_high_pct = 29.0
    writing_gd_pct = 13.0
    maths_high_pct = 24.0


class _Ks4Row:
    year = LATEST
    attainment_8_score = 46.5
    progress_8_score = -0.02


class _StubSession:
    """Returns KS2 rows for the first query and KS4 rows for the second —
    mirroring the payload's query order."""

    def __init__(self):
        self.calls = 0

    def query(self, model):
        self._model = model.__name__
        return self

    def order_by(self, *a):
        return self

    def all(self):
        return [_Ks2Row()] if self._model == "Ks2NationalAverage" else [_Ks4Row()]

    def close(self):
        pass


class _Ks4MissingSession(_StubSession):
    def all(self):
        if self._model == "Ks4NationalAverage":
            raise RuntimeError("relation does not exist")
        return [_Ks2Row()]

    def rollback(self):
        pass


@pytest.fixture()
def payload(monkeypatch):
    from backend import app as app_module
    from backend import database as database_module

    def _run(session_cls):
        monkeypatch.setattr(database_module, "SessionLocal", session_cls)
        return app_module._national_averages_payload(_df())

    return _run


def test_ks4_averages_come_from_the_mart_not_the_dataframe(payload):
    body = payload(_StubSession)
    # Mart value (46.5), NOT the dataframe mean of (50+30)/2 = 40.0
    assert body["secondary"]["attainment_8_score"] == 46.5
    assert body["primary"]["rwm_expected_pct"] == 62.1
    assert body["by_year"][-1]["secondary"]["progress_8_score"] == -0.02


def test_per_subject_higher_standard_nationals_are_surfaced(payload):
    # The SATs chart compares each bar to its own benchmark, so the per-subject
    # higher-standard / greater-depth nationals must reach the payload — not
    # only the combined rwm_high_pct.
    body = payload(_StubSession)
    assert body["primary"]["reading_high_pct"] == 29.0
    assert body["primary"]["writing_gd_pct"] == 13.0
    assert body["primary"]["maths_high_pct"] == 24.0


def test_ks4_secondary_empty_when_mart_missing(payload):
    # No computed stand-in: the UI labels national figures as official DfE
    # data, so an empty mart must yield an empty secondary series.
    body = payload(_Ks4MissingSession)
    assert body["secondary"] == {}
    assert all(not e["secondary"] for e in body["by_year"])
    # The KS2 series is unaffected.
    assert body["primary"]["rwm_expected_pct"] == 62.1
