from db.collection_filter_backfill import (
    accessory_base_name,
    backfill_collection_filter_attributes,
    collection_series_key,
    derive_filter_color_from_collection,
)
from db.models import MasterCollectionRegistry, MasterProduct, MasterProductAttributeValue


def _product(sku: str, collection: str) -> MasterProduct:
    return MasterProduct(
        sku=sku,
        name=sku,
        collection=collection,
        status="active",
        row_hash=sku,
        is_active=True,
    )


def _attr(product: MasterProduct, code: str, value: str) -> MasterProductAttributeValue:
    return MasterProductAttributeValue(
        product_id=product.id,
        sku=product.sku,
        attribute_code=code,
        value=value,
    )


def test_derive_filter_color_from_collection_phrases():
    assert derive_filter_color_from_collection("Anna Snow White") == "White"
    assert derive_filter_color_from_collection("Anna Natural Rift White Oak") == "Natural Oak"
    assert derive_filter_color_from_collection("Cooper Slate Gray") == "Grey"
    assert derive_filter_color_from_collection("Eleanor Ocean Blue") == "Blue"
    assert derive_filter_color_from_collection("Maya Black Rift White Oak") == "Black"


def test_collection_series_and_accessory_helpers():
    assert collection_series_key("Anna Natural Rift White Oak") == "Anna"
    assert collection_series_key("Snow White") is None
    assert accessory_base_name("Snow White - Accessories") == "Snow White"
    assert accessory_base_name("Anna Snow White") is None


def test_backfill_propagates_series_door_style_and_derives_color(catalog_intent_session):
    donor_a = _product("ASW-B12", "Anna Snow White")
    donor_b = _product("ASW-B15", "Anna Snow White")
    empty_a = _product("ANR-B12", "Anna Natural Rift White Oak")
    empty_b = _product("ANR-B15", "Anna Natural Rift White Oak")
    other = _product("OTHER-B12", "Other Line")
    catalog_intent_session.add_all([donor_a, donor_b, empty_a, empty_b, other])
    catalog_intent_session.flush()

    reg_anna_nr = MasterCollectionRegistry(
        code="anna-natural-rift-white-oak",
        name="Anna Natural Rift White Oak",
        path_slug="kitchen-cabinets/anna-natural-rift-white-oak",
        is_active=True,
        aliases={},
    )
    catalog_intent_session.add(reg_anna_nr)
    catalog_intent_session.add_all(
        [
            _attr(donor_a, "door_style", "Shaker"),
            _attr(donor_b, "door_style", "Shaker"),
            _attr(donor_a, "cabinet_construction", "Framed"),
            _attr(donor_b, "cabinet_construction", "Framed"),
            _attr(donor_a, "color", "White"),
            _attr(donor_b, "color", "White"),
            _attr(other, "door_style", "Slab"),
        ]
    )
    catalog_intent_session.commit()

    preview = backfill_collection_filter_attributes(
        catalog_intent_session,
        attributes=["door_style", "color", "cabinet_construction"],
        dry_run=True,
    )

    by_key = {(row["collection"], row["attribute"]): row for row in preview["suggestions"]}
    assert by_key[("Anna Natural Rift White Oak", "door_style")]["value"] == "Shaker"
    assert by_key[("Anna Natural Rift White Oak", "door_style")]["source"].startswith("series:")
    assert by_key[("Anna Natural Rift White Oak", "color")]["value"] == "Natural Oak"
    assert by_key[("Anna Natural Rift White Oak", "color")]["source"] == "collection_name"
    assert by_key[("Anna Natural Rift White Oak", "cabinet_construction")]["value"] == "Framed"
    assert preview["would_update"] == 6  # 2 SKUs × 3 attrs

    applied = backfill_collection_filter_attributes(
        catalog_intent_session,
        attributes=["door_style", "color", "cabinet_construction"],
        dry_run=False,
    )
    catalog_intent_session.commit()
    assert applied["updated"] == 6

    door = (
        catalog_intent_session.query(MasterProductAttributeValue)
        .filter_by(product_id=empty_a.id, attribute_code="door_style")
        .one()
    )
    assert door.value == "Shaker"
    assert door.source_label == "collection_filter_backfill"

    color = (
        catalog_intent_session.query(MasterProductAttributeValue)
        .filter_by(product_id=empty_a.id, attribute_code="color")
        .one()
    )
    assert color.value == "Natural Oak"

    catalog_intent_session.refresh(reg_anna_nr)
    assert reg_anna_nr.aliases["filter_attributes"]["door_style"] == "Shaker"
    assert reg_anna_nr.aliases["filter_attributes"]["color"] == "Natural Oak"


def test_backfill_skips_partial_collections(catalog_intent_session):
    filled = _product("ASW-B12", "Anna Snow White")
    missing = _product("ASW-B15", "Anna Snow White")
    catalog_intent_session.add_all([filled, missing])
    catalog_intent_session.flush()
    catalog_intent_session.add(_attr(filled, "door_style", "Shaker"))
    catalog_intent_session.commit()

    preview = backfill_collection_filter_attributes(
        catalog_intent_session,
        attributes=["door_style"],
        dry_run=True,
    )
    assert preview["suggestion_count"] == 0
    assert preview["would_update"] == 0


def test_backfill_reads_registry_aliases(catalog_intent_session):
    product = _product("BED-B12", "Bedford")
    catalog_intent_session.add(product)
    catalog_intent_session.flush()
    catalog_intent_session.add(
        MasterCollectionRegistry(
            code="bedford",
            name="Bedford",
            path_slug="kitchen-cabinets/bedford",
            is_active=True,
            aliases={"filter_attributes": {"door_style": "Recessed Panel"}},
        )
    )
    catalog_intent_session.commit()

    preview = backfill_collection_filter_attributes(
        catalog_intent_session,
        attributes=["door_style"],
        dry_run=True,
    )
    assert preview["suggestion_count"] == 1
    assert preview["suggestions"][0]["value"] == "Recessed Panel"
    assert preview["suggestions"][0]["source"] == "registry.aliases"


def test_backfill_skips_polluted_suffix_only_collections(catalog_intent_session):
    polluted = _product("SG-B12", "Stone Gray")
    polluted2 = _product("SG-B15", "Stone Gray")
    real = _product("ASG-B12", "Anna Stone Gray")
    real2 = _product("ASG-B15", "Anna Stone Gray")
    catalog_intent_session.add_all([polluted, polluted2, real, real2])
    catalog_intent_session.flush()
    catalog_intent_session.add_all(
        [
            _attr(polluted, "door_style", "Shaker"),
            _attr(polluted2, "door_style", "Shaker"),
            _attr(polluted, "color", "Grey"),
            _attr(polluted2, "color", "Grey"),
            _attr(polluted, "finish", "Stone Gray Painted Finish"),
            _attr(polluted2, "finish", "Stone Gray Painted Finish"),
            _attr(real, "door_style", "Shaker"),
            _attr(real2, "door_style", "Shaker"),
        ]
    )
    catalog_intent_session.commit()

    preview = backfill_collection_filter_attributes(
        catalog_intent_session,
        attributes=["door_style", "color", "finish"],
        dry_run=True,
    )

    assert preview["raw_collection_count"] == 2
    assert preview["collection_count"] == 1
    assert preview["polluted_skipped_count"] == 1
    polluted_rows = [row for row in preview["registry_updates"] if row["collection"] == "Stone Gray"]
    assert polluted_rows == []
