"""The pass packet, the cross-divide candidates, the fingerprint and the settled state (K12.5).

What it cost: a pass had no single input, so a pass on staging read the database as it pleased
and nothing could run it from a button; the two retailer populations (barcodes and shorthand
against clean names and no barcodes) had no reader, so the layer that joins them did not exist;
and "until no decisions remain" had no measurement. SQLite kit, no network."""
from __future__ import annotations

from sqlalchemy import select

from app.models import Listing, ProductVariant, Proposal
from app.services import pass_packet, proposals
from tests.test_precedents import _v6
from tests.test_proposals_load import _key, db  # noqa: F401  (the fixture)


def _split_the_divide(db):
    """Variant 2 becomes the barcoded, shorthand side (no listed text); variant 3 the named side."""
    a, b = db.get(ProductVariant, 2), db.get(ProductVariant, 3)
    a.gtin, a.name, a.quantity_ml = "3145891601008", "Rouge All. Velv 3.5g", 3.5
    b.gtin, b.quantity_ml = None, 3.5
    la = db.scalar(select(Listing).where(Listing.variant_id == 2))
    la.listed_name, la.listed_record_id = None, None
    db.commit()


def test_cross_divide_pairs_a_barcoded_shorthand_row_with_a_named_row_and_never_two_barcoded_rows(db):
    assert pass_packet.cross_divide_candidates(db, [1]) == [], "every variant has listed text: nothing to bridge"
    _split_the_divide(db)
    pairs = pass_packet.cross_divide_candidates(db, [1])
    assert len(pairs) == 1
    pair = pairs[0]
    assert pair["barcoded"]["key"] == _key(db, ProductVariant, 2) and pair["named"]["key"] == _key(db, ProductVariant, 3)
    assert "rouge" in pair["shared_tokens"] and pair["quantity_ml"] == 3.5
    db.get(ProductVariant, 3).gtin = "3145891601015"
    db.commit()
    assert pass_packet.cross_divide_candidates(db, [1]) == [], "two barcodes are a join or a veto, never a candidate"
    hints = proposals.hints(db, "chanel")
    assert not any(l["list"] == "cross_divide" for l in hints["lists"])


def test_the_fingerprint_moves_with_a_listed_word_and_not_with_a_price(db):
    before = pass_packet.fingerprint(db, [1])
    assert before == pass_packet.fingerprint(db, [1])
    listing = db.get(Listing, 2)
    listing.listed_name = listing.listed_name + " Intense"
    db.commit()
    after = pass_packet.fingerprint(db, [1])
    assert after != before
    # A fragment-less listing contributes its collected name, so a name decision moves it too.
    listing.listed_name, listing.listed_record_id = None, None
    db.commit()
    bare = pass_packet.fingerprint(db, [1])
    db.get(ProductVariant, 2).name = "renamed by a decision"
    db.commit()
    assert pass_packet.fingerprint(db, [1]) != bare


def test_status_goes_never_open_settled_and_unsettles_when_a_word_changes(db):
    assert pass_packet.status(db, "chanel")["brands"][0]["state"] == "never"
    data = _v6(db)
    proposals.load(db, data)
    state = pass_packet.status(db, "chanel")["brands"][0]
    assert state["state"] == "open" and state["layer"] == "product_lines", state
    proposals.withdraw(db, data["pass"]["name"], "rehearsal", "rian")
    settled = {"pass": {"name": "claude/2026-09-18/chanel-settled", "kind": "session", "process_version": data["pass"]["process_version"],
                        "rules_version": data["pass"]["rules_version"], "generator": "claude-session", "verdict": "settled",
                        "fingerprint": pass_packet.fingerprint(db, [1]), "note": "nothing open in any layer"},
               "brand": "chanel", "proposals": []}
    from app.models.catalog import IDENTITY_RULES_VERSION
    from app.services.proposal_rules import PROCESS_VERSION
    settled["pass"]["process_version"], settled["pass"]["rules_version"] = PROCESS_VERSION, IDENTITY_RULES_VERSION
    proposals.load(db, settled)
    whole = pass_packet.status(db)
    assert whole["brands"][0]["state"] == "settled" and whole["done"] is True and whole["line"].startswith("done:")
    listing = db.get(Listing, 1)
    listing.listed_name = "Rouge Allure Velvet Extreme"
    db.commit()
    whole = pass_packet.status(db)
    assert whole["brands"][0]["state"] == "unsettled" and "listed words changed" in whole["brands"][0]["why"] and whole["done"] is False


def test_the_packet_carries_what_the_specification_lists_and_nothing_a_pass_would_need_beyond_it(db):
    _split_the_divide(db)
    data = _v6(db)
    proposals.load(db, data)
    lead = db.scalar(select(Proposal).where(Proposal.field == "attribute:color"))
    proposals.approve(db, "chanel", data["pass"]["name"], scope=None, by="rian", counter=[str(lead.uid)], note="not like that")
    pk = pass_packet.packet(db, "chanel")
    for key in ("process_version", "rules_version", "brand", "layer", "layers", "state", "fingerprint", "product_lines", "product_variants",
                "populations", "cross_divide_candidates", "hints", "notes", "parked", "precedents", "principles", "attention"):
        assert key in pk, key
    assert pk["brand"]["family"][0]["slug"] == "chanel" and pk["layer"] == "product_lines"
    bare = next(l for v in pk["product_variants"] for l in v["listings"] if not l["has_fragment"] and l["listed_name"] is None)
    assert bare["collected_name"] == "Rouge All. Velv 3.5g", "a fragment-less listing carries the name a pass may cite"
    assert pk["cross_divide_candidates"][0]["barcoded"]["name"] == "Rouge All. Velv 3.5g"
    assert any(n.get("wants") == "a different suggestion" for n in pk["notes"]["notes"])
    assert pk["principles"] and "## " in pk["principles"]
    assert pk["attention"]["leave_high_after"] == 3
    packet_layer = pass_packet.packet(db, "chanel", layer="attributes")["layer"]
    assert packet_layer == "attributes", "the caller may name the layer"
