"""B2 measurement correctness. Does not demand Planner score lifts."""

import json
from pathlib import Path

import pytest
from scripts.measure_generation_reliability_13a import corpus
from scripts.measure_planner_selection_13b_b2 import (
    FROZEN_RAW_CONTROL,
    PROTECTED_OUTPUTS,
    measure,
    raw_spec,
)
from src.domain.app_blocks.planner import product_intent_from_spec, select_capabilities

ROOT = Path(__file__).resolve().parents[1]


def test_primary_denominator_stays_108_admitted_prompts():
    # GR-05 appended a 10-row "support" stratum (13A-121..130, admitted
    # prompts 108 -> 118) and GR-06 appended a 10-row "approval" stratum
    # (13A-131..140, 118 -> 128) after the frozen 13A-01/13A-02 120-row set.
    # This test's name predates those admissions; the B2-era 108-row oracle
    # itself is unchanged, just no longer the *entire* admitted set. See
    # docs/audits/GR05_EXIT_REVIEW.md and docs/audits/GR06_EXIT_REVIEW.md.
    rows = corpus(ROOT / "scripts/phase_13a_corpus.txt")
    assert len(rows) == 140
    assert sum(row["oracle_kind"] == "admitted" for row in rows) == 128
    assert sum(row["oracle_kind"] == "clarify" for row in rows) == 10
    assert sum(row["oracle_kind"] == "admission_required" for row in rows) == 2


def test_gold_never_enters_raw_planner_input():
    rows = corpus(ROOT / "scripts/phase_13a_corpus.txt")
    crm = next(row for row in rows if row["id"] == "13A-002")
    spec = raw_spec(crm["prompt"])
    intent = product_intent_from_spec(spec)
    assert intent.purpose == crm["prompt"]
    assert intent.first_build_goal == ""
    assert intent.entity_names == []
    assert intent.workflow_names == []
    predicted = {block for _, block, _ in select_capabilities(intent)}
    assert "crm.lead" not in crm["prompt"]
    assert "crm.pipeline" not in crm["prompt"]
    assert intent.entity_names == []
    assert predicted == set(crm["expected_product_blocks"])


def test_refuse_writes_into_frozen_13a_receipts():
    for protected in PROTECTED_OUTPUTS:
        with pytest.raises(ValueError, match="Refuse writes into frozen"):
            measure(protected, kind="before")
    first = ROOT / ".test-tmp" / "b2-measure"
    first.mkdir(parents=True, exist_ok=True)
    (first / "scorecard.json").write_text("{}\n", encoding="utf-8")
    try:
        with pytest.raises(ValueError, match="must not be overwritten"):
            measure(first, kind="before")
    finally:
        (first / "scorecard.json").unlink(missing_ok=True)
        first.rmdir()


def test_before_score_receipt_preserves_frozen_raw_control():
    scorecard = json.loads(
        (ROOT / "docs/audits/fixtures/13b_b2_before/scorecard.json").read_text(encoding="utf-8")
    )
    assert scorecard["before_score_reproduced"] is True
    assert scorecard["frozen_13a02_comparison"]["observed"] == FROZEN_RAW_CONTROL
    assert scorecard["predicted_set_disagreements_vs_13a02"]["numerator"] == 0
    assert scorecard["mixed_quote_exact"]["preserved"] is True


def test_after_score_receipt_keeps_primary_denominator_and_mixed_quote():
    scorecard = json.loads(
        (ROOT / "docs/audits/fixtures/13b_b2_after_gr04/scorecard.json").read_text(
            encoding="utf-8"
        )
    )
    assert scorecard["raw_planner_exact_product"] == "107/108"
    assert scorecard["raw_planner_precision"] == "137/137"
    assert scorecard["raw_planner_recall"] == "137/139"
    assert scorecard["crm_exact_product"] == "10/10"
    assert scorecard["crm_recall"] == "23/23"
    assert scorecard["documents_exact"] == "10/10"
    assert scorecard["catalog_exact"] == "10/10"
    assert scorecard["mixed_quote_exact"]["preserved"] is True
    assert scorecard["booking_contact_false_positives"]["numerator"] == 0
    assert scorecard["negation_false_positives"]["numerator"] == 0
    assert scorecard["discovery_to_planner_semantic_loss"]["denominator"] == 104


def test_13a02_receipts_remain_untouched():
    freeze = json.loads(
        (ROOT / "docs/audits/fixtures/13a_run_02_freeze.json").read_text(encoding="utf-8")
    )
    scorecard = json.loads(
        (ROOT / "docs/audits/fixtures/13a_run_02/scorecard.json").read_text(encoding="utf-8")
    )
    assert freeze["raw_planner_exact_product"] == "76/108"
    assert freeze["raw_planner_precision"] == "104/118"
    assert freeze["raw_planner_recall"] == "104/139"
    control = scorecard["raw_text_planner_control_only"]
    assert control["exact_product_match_rate"]["numerator"] == 76
    assert control["planner_precision"]["numerator"] == 104
    assert control["planner_recall"]["numerator"] == 104
    assert scorecard["raw_control_by_stratum"]["crm"]["exact_product_match_rate"] == {
        "numerator": 3,
        "denominator": 10,
        "rate": 0.3,
        "unmeasured_reason": None,
    }
