"""
test_coverage.py — the derived coverage registry (ARCHITECTURE §5).

Guards the no-false-coverage-claim invariants made structural:
  - the S1–S11 denominator is parsed INDEPENDENTLY from the taxonomy doc, and fails LOUD on a short parse
    (never silently returns a subset that would hide a class).
  - covered-classes derive ACROSS the §8 manifest bifurcation (covers list | class singular | shipped cell).
  - the three structural gaps fire (blind-spot, uncovered class, inert ratchet) and grades are GRADED, not a
    boolean — a cross-file defect counts ONCE (deduped), so n cells != rate-capability.
  - the real repo reports ok=True with zero gaps: the structural proof that "100%" is real, today.
"""
import importlib.util, os
import pytest

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


def _load(name, path):
    spec = importlib.util.spec_from_file_location(name, path)
    m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m); return m


cov = _load("sg_ledger", os.path.join(ROOT, "ledger.py"))


def _det(tmp, did, **kw):
    d = {"id": did, "_dir": str(tmp / did)}; d.update(kw); (tmp / did).mkdir(exist_ok=True); return d


def _cell(cls, sym, sha, cid, **kw):
    c = {"class": cls, "canonical_symbol": sym, "fix_sha": sha, "id": cid, "file": kw.get("file", cid + ".ts"),
         "_dir": kw.get("_dir", "/nowhere/" + cid)}; c.update(kw); return c


# --- independent denominator ---

def test_taxonomy_parses_thirteen_from_real_doc():
    assert cov.taxonomy_classes() == [f"S{i}" for i in range(1, 14)]


def test_taxonomy_fails_loud_on_short_parse(tmp_path):
    doc = tmp_path / "t.md"; doc.write_text("| S1 | only one class |\n| S2 | two |\n")
    with pytest.raises(SystemExit):
        cov.taxonomy_classes(str(doc))


# --- covered-classes across the manifest bifurcation ---

def test_detector_classes_union(tmp_path):
    llm = _det(tmp_path, "llm1", covers=["S1", "S2"])
    exc = _det(tmp_path, "exc1", **{"class": "S11"})
    ship = _det(tmp_path, "ship1")
    shipped = _cell("S9", "x", "h", "c9", _dir=str(tmp_path / "ship1" / "cells"))
    assert cov.detector_classes(llm, []) == {"S1", "S2"}
    assert cov.detector_classes(exc, []) == {"S11"}
    assert cov.detector_classes(ship, [shipped]) == {"S9"}  # proven by the cell it ships, no `covers`/`class`


# --- gaps fire ---

def test_blind_spot_and_uncovered_when_class_has_nothing(tmp_path):
    classes = ["S1", "S2"]
    cells = [_cell("S1", "a", "h1", "c1")]
    dets = [_det(tmp_path, "d1", covers=["S1"])]
    reg = cov.build(cells, dets, [], classes)
    kinds = {(g["kind"], g["class"]) for g in reg["gaps"]}
    assert ("blind-spot", "S2") in kinds and ("uncovered", "S2") in kinds
    assert reg["summary"]["ok"] is False


def test_inert_ratchet_when_confirmed_class_uncovered(tmp_path):
    classes = ["S1"]
    cells = [_cell("S1", "a", "h1", "c1")]
    dets = [_det(tmp_path, "d1", covers=["S1"])]
    confirmed = [{"class": "S9", "file": "x.ts", "symbol": "y", "ref": "#99"}]  # S9 has no detector here
    reg = cov.build(cells, dets, confirmed, classes)
    assert any(g["kind"] == "inert-ratchet" and g["class"] == "S9" for g in reg["gaps"])
    assert reg["summary"]["ok"] is False


# --- grade, not boolean: dedup by defect ---

def test_crossfile_defect_counts_once(tmp_path):
    classes = ["S1"]
    # two FILES, one fix_sha+symbol = ONE defect (the 2FA-pair shape) → thin, NOT rate-capable
    cells = [_cell("S1", "buildSessionPayload enforce2fa", "ead618d", "c_refresh", file="refresh.ts"),
             _cell("S1", "buildSessionPayload enforce2fa", "ead618d", "c_session", file="session.ts")]
    dets = [_det(tmp_path, "d1", covers=["S1"])]
    reg = cov.build(cells, dets, [], classes)
    g = reg["classes"][0]
    assert g["n_cells"] == 2 and g["n_defects"] == 1 and g["sample"] == "point-estimate"
    assert len(reg["defects"]) == 1


def test_covers_assertion_without_shipped_cell_is_not_deterministic(tmp_path):
    # a wrapped exec detector covers S4+S5 but ships only an S4 conformance cell → S5 must grade 'asserted',
    # never 'deterministic' (no-false-coverage-claim: covers is a claim, a shipped cell is proof).
    classes = ["S4", "S5"]
    wrap = _det(tmp_path, "semgrep", **{"kind": "exec", "covers": ["S4", "S5"]})
    s4cell = _cell("S4", "sqli", "h4", "c4", _dir=str(tmp_path / "semgrep" / "cells"))
    s5cell = _cell("S5", "xss", "h5", "c5")  # exists, but NOT shipped under the detector
    reg = cov.build([s4cell, s5cell], [wrap], [], classes)
    by = {g["class"]: g for g in reg["classes"]}
    assert by["S4"]["coverage"] == "deterministic"   # ships an S4 cell → proven
    assert by["S5"]["coverage"] == "asserted"         # covers-only → claim, not proven


def test_rate_capable_needs_three_distinct_defects(tmp_path):
    classes = ["S3"]
    cells = [_cell("S3", f"sym{i}", f"h{i}", f"c{i}") for i in range(3)]
    dets = [_det(tmp_path, "d1", covers=["S3"])]
    reg = cov.build(cells, dets, [], classes)
    assert reg["classes"][0]["sample"] == "rate-capable"


# --- the structural proof on the real repo ---

def test_real_repo_has_no_gaps():
    reg = cov.build(cov.bench.load_cells(), cov.manifest.load(ROOT)[0], cov.load_confirmed(), cov.taxonomy_classes())
    assert reg["gaps"] == [] and reg["summary"]["ok"] is True
    assert reg["summary"]["rate_capable"] == ["S2", "S3"]  # agrees with the taxonomy curation
