"""Starter Library catalog contract: metadata, admission, proposed queue."""

from src.domain.starter_library.catalog import (
    FORBIDDEN_STARTER_IDS,
    STARTER_CATALOG_SCHEMA_VERSION,
    contract_map_payload,
    get_contract,
    known_contract_ids,
    known_proposed_ids,
    list_contracts,
    list_proposed_contracts,
    merge_contract_map,
)

REQUIRED_FIELDS = (
    "id",
    "layer",
    "description",
    "use_when",
    "avoid_when",
    "supports",
    "requires",
    "compatible_with",
    "states",
    "accessibility",
    "fallbacks",
    "admission",
)


def test_admitted_catalog_is_self_describing():
    assert len(known_contract_ids()) == 70
    assert len(known_proposed_ids()) == 14
    for item in list_contracts():
        assert item.admission == "admitted"
        assert item.description.strip()
        assert item.use_when
        assert item.avoid_when
        assert item.accessibility
        dumped = item.model_dump()
        for field in REQUIRED_FIELDS:
            assert field in dumped, (item.id, field)


def test_proposed_ids_are_not_slot_valid():
    admitted = known_contract_ids()
    proposed = known_proposed_ids()
    assert admitted.isdisjoint(proposed)
    assert "layout.page_header" in admitted
    assert "filter.bar" in admitted
    assert "nav.pagination" in admitted
    assert "status.badge" in admitted
    assert "record.list" in admitted
    assert "record.card" in admitted
    assert "search.box" in admitted
    assert "ui.datepicker" in proposed
    assert "stat.card" in proposed
    assert "layout.page_header" not in proposed
    assert "record.list" not in proposed
    assert "record.card" not in proposed
    assert "search.box" not in proposed
    payload = contract_map_payload()
    assert {row["id"] for row in payload["proposed"]} == proposed
    assert all(row["admission"] == "proposed" for row in payload["proposed"])


def test_catalog_does_not_absorb_product_or_shell_ids():
    combined = known_contract_ids() | known_proposed_ids()
    assert FORBIDDEN_STARTER_IDS.isdisjoint(combined)
    for item in list_proposed_contracts():
        assert item.layer in {"foundation", "primitive", "composite", "adapter"}
        assert not item.id.startswith(("crm.", "auth.", "billing.", "customer."))


def test_data_backed_contracts_declare_states():
    table = get_contract("record.table")
    assert "empty" in table.states
    assert "error" in table.states
    assert "records.query" in table.compatible_with
    listing = get_contract("record.list")
    assert "empty" in listing.states
    assert "layout.page_header" in listing.requires
    assert "record.table" in listing.requires
    assert "record.card" in listing.compatible_with
    card = get_contract("record.card")
    assert "status.badge" in card.requires
    config = get_contract("state.configuration_required")
    assert "configuration_required" in config.states
    assert config.runtime_dependencies
    assert config.fallbacks["admin"]


def test_merge_preserves_implementation_and_catalog_envelope():
    payload = contract_map_payload()
    merged = merge_contract_map(
        {"contracts": [{"id": "record.table", "implementation": "RecordTable.vue"}]},
        payload,
    )
    assert merged["catalog_schema_version"] == STARTER_CATALOG_SCHEMA_VERSION
    assert merged["codegen"]["prefer_existing"] is True
    mapped = {item["id"]: item for item in merged["contracts"]}
    assert mapped["record.table"]["implementation"] == "RecordTable.vue"
    assert mapped["record.table"]["use_when"]
    assert mapped["ui.button"]["implementation"] is None
    assert "proposed" in merged
