"""The hidden tier is hidden only if the generator keeps it so. This is the gate.

Two checks. The first is structural and exact: for every seed the free screen
is byte-identical with the overlay on or off, for every overlay the screen can
carry. The second is distributional: across seeds, the screen features a
policy could key on do not separate hidden from benign beyond noise. The
generator draws the tier BEFORE the template and the screen, so the two
populations are the same draw; this test is what would catch a regression that
made them differ.
"""

from __future__ import annotations

import math

import pytest

from alert_triage.generator import canonical_json, compatible_overlays, generate, screen_of

ALL = range(4096)


@pytest.fixture(scope="module")
def pairs():
    out = []
    for s in ALL:
        base = generate(s, overlay=None)
        if base["template"].startswith("S"):
            continue
        out.append((s, base))
    return out


def test_overlay_never_touches_the_screen(pairs) -> None:
    for seed, base in pairs:
        before = canonical_json(screen_of(base))
        for kind in compatible_overlays(base):
            overlaid = generate(seed, overlay=kind)
            assert overlaid["label"] == "suspicious" and overlaid["overlay"] == kind
            assert canonical_json(screen_of(overlaid)) == before, (seed, kind)


def test_the_seed_overlay_is_one_of_the_compatible_kinds(pairs) -> None:
    for seed, base in pairs:
        w = generate(seed)
        if w["overlay"]:
            assert w["overlay"] in compatible_overlays(base)


def _features(w) -> list[float]:
    c = w["customer"]
    screen = screen_of(w)
    trig = screen["triggering_transactions"]
    amounts = [t["amount"] for t in trig]
    return [
        float(c["prior_alerts"]),
        float(c["prior_sars"]),
        float(c["pep"]),
        float(sum(1 for cp in screen["screen_counterparties"] if cp["direction"] == "out")),
        float(sum(1 for a in amounts if a % 100000 == 0)) / max(1, len(amounts)),
        float(len(trig)),
        float(len({t["branch"] for t in trig if t["branch"]})),
        float(sum(r["wires_out"] > 0 for r in w["summary"])),
        float(screen["alert"]["rule"] == "R-STR-01"),
        float(c["expected_monthly_cash"] > 0),
    ]


def test_screen_features_do_not_separate_hidden_from_benign() -> None:
    """Per-feature z-test between the two populations; nothing beyond 4 sigma."""
    benign, hidden = [], []
    for s in ALL:
        w = generate(s)
        if w["tier"] == "benign":
            benign.append(_features(w))
        elif w["tier"] == "hidden":
            hidden.append(_features(w))
    assert len(hidden) > 400
    for j in range(len(benign[0])):
        b = [f[j] for f in benign]
        h = [f[j] for f in hidden]
        mb, mh = sum(b) / len(b), sum(h) / len(h)
        vb = sum((x - mb) ** 2 for x in b) / max(1, len(b) - 1)
        vh = sum((x - mh) ** 2 for x in h) / max(1, len(h) - 1)
        se = math.sqrt(vb / len(b) + vh / len(h)) or 1e-9
        z = abs(mb - mh) / se
        assert z < 4.0, f"feature {j}: benign {mb:.3f} vs hidden {mh:.3f}, z={z:.1f}"
