"""A word list is the pass's input, never a person's queue (K11.2).

The real cost. On a copy of `dfp-2026-09-17-post-chain.dump` the brand index drew 357 brands and
938 open proposals, and every one of them came from a `rule:<list>:6` pass written in one instant
by `backfill rule_proposals`. Rian spent two days answering them believing he was reviewing AI
proposals; the AI pass had never run, and rule 1 of his 17 Sep ruling says the programmatic stage's
output is never reviewed by him at all. Pairing W14's option B with option D is what put it there.

So: a pass whose kind is not a review kind is not on the index and not on a sheet, its rows are
KEPT (withdrawal is reversible, and a pass reads them as hints), and naming one explicitly still
draws it so the history stays readable.
"""

from __future__ import annotations

from sqlalchemy import select

from app.models import Proposal, ProposalPass
from app.services import proposals
from tests.test_proposals_load import _counts, _file, db  # noqa: F401 (the fixture)


def _rule_file(db, name="rule:drink_words:6"):
    """The same rows, loaded as the word-list pass `backfill rule_proposals` writes."""
    data = _file(db, name=name)
    data["pass"]["kind"] = "rule"
    data["pass"]["generator"] = "rule"
    return data


def test_a_word_list_pass_is_not_on_the_brand_index(db):
    proposals.load(db, _rule_file(db))
    assert proposals.sheets(db) == [], "938 rule rows put 357 brands on rian's index"


def test_a_word_list_pass_is_not_drawn_on_the_sheet_but_its_rows_are_kept(db):
    proposals.load(db, _rule_file(db))
    before = _counts(db)
    sheet = proposals.sheet(db, "chanel")
    assert sheet["groups"] == [] and sheet["counts"] == {}
    # The pass is still listed, so a person can see the list exists and read it on purpose.
    assert [p["name"] for p in sheet["passes"]] == ["rule:drink_words:6"]
    assert _counts(db) == before, "a read writes nothing, and withdrawal never deletes a row"
    assert db.scalar(select(Proposal).where(Proposal.status == "open")) is not None


def test_naming_the_word_list_pass_explicitly_still_draws_it(db):
    proposals.load(db, _rule_file(db))
    named = proposals.sheet(db, "chanel", pass_name="rule:drink_words:6")
    assert named["groups"], "a withdrawn or rule pass stays readable when it is asked for by name"
    assert named["counts"]["open"] >= 1


def test_a_session_pass_is_still_the_queue(db):
    proposals.load(db, _file(db))
    index = proposals.sheets(db)
    assert [e["brand_slug"] for e in index] == ["chanel"] and index[0]["open"] >= 1
    assert proposals.sheet(db, "chanel")["groups"], "the AI pass is what rian reviews"


def test_the_two_kinds_together_show_only_the_session_pass(db):
    proposals.load(db, _rule_file(db))
    proposals.load(db, _file(db))
    index = proposals.sheets(db)
    assert len(index) == 1
    # The index's count must equal what the sheet draws: the bug K9 fixed was the two disagreeing.
    drawn = sum(len(g["rows"]) for g in proposals.sheet(db, "chanel")["groups"])
    assert index[0]["open"] + index[0]["parked"] + index[0]["stale"] == drawn


def test_the_hints_read_gives_a_pass_what_each_list_saw_and_why(db):
    proposals.load(db, _rule_file(db))
    out = proposals.hints(db, "chanel")
    assert out["total"] == 4 and [e["list"] for e in out["lists"]] == ["drink_words"]
    entry = out["lists"][0]
    assert entry["pass_name"] == "rule:drink_words:6" and entry["count"] == 4
    reasons = [s["reason"] for s in entry["suggestions"]]
    assert any(r and "shade" in r for r in reasons), reasons
    # A pair's two sides are named: "these two read as one" is unanswerable without them.
    pair = next(s for s in entry["suggestions"] if s["entity_type"] == "suggestion")
    assert len(pair["sides"]) == 2 and all(s["key"] for s in pair["sides"])


def test_the_hints_read_still_answers_after_the_pass_is_withdrawn(db):
    """Withdrawal takes a list out of the human queue, not out of the pass's evidence."""
    proposals.load(db, _rule_file(db))
    proposals.withdraw(db, "rule:drink_words:6", "the programmatic stage is never reviewed", by=1)
    out = proposals.hints(db, "chanel")
    assert out["total"] == 4 and out["lists"][0]["withdrawn"] is True
    assert out["lists"][0]["withdrawn_reason"] == "the programmatic stage is never reviewed"
    assert proposals.sheets(db) == []


def test_a_session_pass_is_never_returned_as_a_hint(db):
    """A hint is input. An AI proposal is a question, and must never be fed back as its own input."""
    proposals.load(db, _file(db))
    out = proposals.hints(db, "chanel")
    assert out["lists"] == [] and out["total"] == 0
