from db.collection_landing_pages import get_collection_landing_page, upsert_collection_landing_page
from db.channel_listing_path import list_listing_paths, upsert_listing_path
from db.listing_intersections import (
    compact_filter_value,
    list_listing_intersections,
    materialize_listing_intersections,
)
from db.models import ChannelListingPath, ChannelListingPathTarget


def test_materialize_listing_intersections_creates_generic_seo_paths(catalog_intent_session):
    session = catalog_intent_session
    rows = materialize_listing_intersections(
        session,
        base_path_slug="kitchen-cabinets",
        group_path_slug="kitchen-cabinets/anna-snow-white",
        facet_attribute="cabinet_type",
        options=["Base Cabinets", "Wall Cabinets"],
        magento_category_id=501,
        shopify_collection_id="gid://shopify/Collection/123",
        shopify_handle_prefix="kitchen-cabinets-anna-snow-white",
    )

    assert [row["seo_path_slug"] for row in rows] == [
        "kitchen-cabinets/anna-snow-white/base-cabinets",
        "kitchen-cabinets/anna-snow-white/wall-cabinets",
    ]
    assert rows[1]["filter_payload"] == {
        "attribute": "cabinet_type",
        "label": "Wall Cabinets",
        "value": "wallcabinets",
        "slug": "wall-cabinets",
    }
    assert rows[1]["filter_type"] == "attribute"


def test_materialize_listing_intersections_can_assert_category_filters(catalog_intent_session):
    session = catalog_intent_session
    rows = materialize_listing_intersections(
        session,
        base_path_slug="kitchen-cabinets",
        group_path_slug="kitchen-cabinets/belmont-drift-white",
        facet_attribute="cabinet_type",
        options=["Wall Cabinets"],
        magento_category_id=501,
        use_category_filters=True,
    )

    assert rows[0]["seo_path_slug"] == "kitchen-cabinets/belmont-drift-white/wall-cabinets"
    assert rows[0]["filter_type"] == "category"
    assert rows[0]["filter_attribute"] == "category_ids"
    assert rows[0]["filter_category_path"] == "kitchen-cabinets/wall-cabinets"
    assert rows[0]["filter_payload"]["type"] == "category"
    assert rows[0]["channel_payload"]["magento"]["filter_category_path"] == "kitchen-cabinets/wall-cabinets"


def test_collection_landing_page_includes_shopping_intersections(catalog_intent_session):
    session = catalog_intent_session
    upsert_collection_landing_page(
        session,
        {"category_l1": "Kitchen Cabinets", "collection": "Anna Snow White", "title": "Anna Snow White"},
    )

    page = get_collection_landing_page(session, "kitchen-cabinets/anna-snow-white")

    assert page is not None
    intersections = page["shopping_intersections"]
    assert len(intersections) >= 5
    wall = next(item for item in intersections if item["filter_slug"] == "wall-cabinets")
    assert wall == {
        "title": "Wall Cabinets",
        "label": "Wall Cabinets",
        "seo_path": "kitchen-cabinets/anna-snow-white/wall-cabinets",
        "url": "/kitchen-cabinets/anna-snow-white/wall-cabinets.html",
        "shopify_url": "/collections/anna-snow-white?category_ids=kitchen-cabinets/wall-cabinets",
        "filter_type": "category",
        "filter_attribute": "category_ids",
        "filter_value": "kitchen-cabinets/wall-cabinets",
        "filter_slug": "wall-cabinets",
        "filter_category_path": "kitchen-cabinets/wall-cabinets",
        "filter_category_id": None,
        "channel": {
            "shopify": {
                "collection_id": None,
                "handle": "anna-snow-white",
                "target_path_slug": "kitchen-cabinets/anna-snow-white",
                "filter": {
                    "type": "category",
                    "attribute": "category_ids",
                    "label": "Wall Cabinets",
                    "value": "kitchen-cabinets/wall-cabinets",
                    "slug": "wall-cabinets",
                    "category_path": "kitchen-cabinets/wall-cabinets",
                    "category_id": None,
                },
            }
        },
    }


def test_compact_filter_value_is_not_cabinet_specific():
    assert compact_filter_value("Solid Core") == "solidcore"
    assert compact_filter_value("48 Inch") == "48inch"


def test_list_listing_intersections_filters_by_group(catalog_intent_session):
    session = catalog_intent_session
    materialize_listing_intersections(
        session,
        base_path_slug="interior-doors",
        group_path_slug="interior-doors/shaker",
        facet_attribute="door_core",
        options=["Solid Core"],
    )

    rows = list_listing_intersections(session, group_path_slug="interior-doors/shaker")

    assert len(rows) == 1
    assert rows[0]["seo_path_slug"] == "interior-doors/shaker/solid-core"


def test_listing_path_round_trips_shopping_facet_attribute(catalog_intent_session):
    session = catalog_intent_session
    upsert_listing_path(
        session,
        path_slug="interior-doors",
        title="Interior Doors",
        path_kind="hub",
        shopping_facet_attribute="door_core",
    )

    rows = list_listing_paths(session, search="interior-doors")

    assert rows[0]["path_slug"] == "interior-doors"
    assert rows[0]["shopping_facet_attribute"] == "door_core"


def test_sync_shopping_intersections_for_collection_uses_hub_defaults(catalog_intent_session):
    session = catalog_intent_session
    from db.listing_intersections import sync_shopping_intersections_for_collection

    collection = {
        "path_slug": "kitchen-cabinets/anna-snow-white",
        "category_l1": "Kitchen Cabinets",
        "collection": "Anna Snow White",
    }
    rows = sync_shopping_intersections_for_collection(session, collection, magento_category_id=501)

    assert len(rows) >= 5
    assert rows[0]["seo_path_slug"] == "kitchen-cabinets/anna-snow-white/base-cabinets"
    assert rows[1]["seo_path_slug"] == "kitchen-cabinets/anna-snow-white/wall-cabinets"


def test_sync_shopping_intersections_includes_nested_cabinet_type_options(catalog_intent_session):
    session = catalog_intent_session
    from db.listing_intersections import shopping_intersections_for_collection, sync_shopping_intersections_for_collection

    collection = {
        "path_slug": "kitchen-cabinets/anna-snow-white",
        "category_l1": "Kitchen Cabinets",
        "collection": "Anna Snow White",
    }
    rows = sync_shopping_intersections_for_collection(session, collection, magento_category_id=501)
    paths = {row["seo_path_slug"] for row in rows}

    assert "kitchen-cabinets/anna-snow-white/wall-cabinets/corner-wall" in paths

    metadata_rows = shopping_intersections_for_collection(session, "kitchen-cabinets/anna-snow-white")
    corner = next(
        item
        for item in metadata_rows
        if item["seo_path"] == "kitchen-cabinets/anna-snow-white/wall-cabinets/corner-wall"
    )

    assert corner["filter_type"] == "category"
    assert corner["filter_attribute"] == "category_ids"
    assert corner["filter_value"] == "kitchen-cabinets/wall-cabinets/corner-wall"
    assert corner["filter_slug"] == "corner-wall"
    assert corner["filter_category_path"] == "kitchen-cabinets/wall-cabinets/corner-wall"


def test_sync_shopping_intersections_prefers_existing_taxonomy_children(catalog_intent_session):
    session = catalog_intent_session
    from db.listing_intersections import shopping_intersections_for_collection, sync_shopping_intersections_for_collection
    from db.models import MasterTaxonomyNode

    base = MasterTaxonomyNode(
        parent_id=None,
        node_kind="category",
        code="base-cabinets",
        name="Base Cabinets",
        path_slug="kitchen-cabinets/base-cabinets",
        sort_order=10,
    )
    session.add(base)
    session.flush()
    session.add(
        MasterTaxonomyNode(
            parent_id=base.id,
            node_kind="category",
            code="angle-end-base-cabinet",
            name="Angle End Base Cabinet",
            path_slug="kitchen-cabinets/base-cabinets/angle-end-base-cabinet",
            sort_order=10,
        )
    )
    session.flush()

    sync_shopping_intersections_for_collection(
        session,
        {
            "path_slug": "kitchen-cabinets/anna-snow-white",
            "category_l1": "Kitchen Cabinets",
            "collection": "Anna Snow White",
        },
        magento_category_id=501,
    )

    metadata_rows = shopping_intersections_for_collection(session, "kitchen-cabinets/anna-snow-white")
    angle = next(
        item
        for item in metadata_rows
        if item["seo_path"] == "kitchen-cabinets/anna-snow-white/base-cabinets/angle-end-base-cabinet"
    )

    assert angle["filter_type"] == "category"
    assert angle["filter_attribute"] == "category_ids"
    assert angle["filter_value"] == "kitchen-cabinets/base-cabinets/angle-end-base-cabinet"
    assert angle["filter_slug"] == "angle-end-base-cabinet"
    assert angle["filter_category_path"] == "kitchen-cabinets/base-cabinets/angle-end-base-cabinet"
    assert angle["title"] == "Angle End Base Cabinet"


def test_detail_options_do_not_fallback_to_shorthand_for_explicit_l2_paths(catalog_intent_session):
    session = catalog_intent_session
    from db.listing_intersections import _detail_options_for_shopping_option

    options = _detail_options_for_shopping_option(
        session,
        "kitchen-cabinets",
        "Wall Cabinets",
        selected_paths=["kitchen-cabinets/wall-cabinets/angle-end-wall-cabinet"],
    )

    assert options == []


def test_taxonomy_child_options_preserve_selected_l2_order(catalog_intent_session):
    session = catalog_intent_session
    from db.listing_intersections import _taxonomy_child_options_for_shopping_option
    from db.models import MasterTaxonomyNode

    parent = MasterTaxonomyNode(
        parent_id=None,
        node_kind="category",
        code="base-cabinets",
        name="Base Cabinets",
        path_slug="kitchen-cabinets/base-cabinets",
        sort_order=10,
    )
    session.add(parent)
    session.flush()
    session.add_all(
        [
            MasterTaxonomyNode(
                parent_id=parent.id,
                node_kind="category",
                code="single-door",
                name="Single Door",
                path_slug="kitchen-cabinets/base-cabinets/single-door",
                sort_order=10,
            ),
            MasterTaxonomyNode(
                parent_id=parent.id,
                node_kind="category",
                code="drawer-base",
                name="Drawer Base",
                path_slug="kitchen-cabinets/base-cabinets/drawer-base",
                sort_order=20,
            ),
            MasterTaxonomyNode(
                parent_id=parent.id,
                node_kind="category",
                code="sink-base",
                name="Sink Base",
                path_slug="kitchen-cabinets/base-cabinets/sink-base",
                sort_order=30,
            ),
        ]
    )
    session.flush()

    options = _taxonomy_child_options_for_shopping_option(
        session,
        "kitchen-cabinets",
        "Base Cabinets",
        selected_paths=[
            "kitchen-cabinets/base-cabinets/sink-base",
            "kitchen-cabinets/base-cabinets/single-door",
            "kitchen-cabinets/base-cabinets/drawer-base",
        ],
    )

    assert [item["category_path"] for item in options] == [
        "kitchen-cabinets/base-cabinets/sink-base",
        "kitchen-cabinets/base-cabinets/single-door",
        "kitchen-cabinets/base-cabinets/drawer-base",
    ]


def test_intersection_group_paths_exclude_facets_and_dedupe_aliases(catalog_intent_session):
    session = catalog_intent_session
    from db.channel_listing_path import upsert_listing_path
    from db.listing_intersections import intersection_group_paths_for_hub
    from db.models import MasterTaxonomyNode

    upsert_listing_path(
        session,
        path_slug="kitchen-cabinets",
        title="Kitchen Cabinets",
        path_kind="hub",
        shopping_facet_attribute="cabinet_type",
    )
    upsert_listing_path(
        session,
        path_slug="kitchen-cabinets/wall-cabinets",
        title="Wall Cabinets",
        path_kind="facet",
        hub_path_slug="kitchen-cabinets",
    )
    session.add(
        MasterTaxonomyNode(
            parent_id=None,
            node_kind="collection",
            code="anna-stone-gray",
            name="Anna Stone Gray",
            path_slug="kitchen-cabinets/anna-stone-gray",
        )
    )
    session.add(
        MasterTaxonomyNode(
            parent_id=None,
            node_kind="collection",
            code="anna-stone-gray-kitchen-cabinets",
            name="Anna Stone Gray Kitchen Cabinets",
            path_slug="kitchen-cabinets/anna-stone-gray-kitchen-cabinets",
        )
    )
    session.flush()

    groups = intersection_group_paths_for_hub(session, "kitchen-cabinets")
    slugs = {row["path_slug"] for row in groups}

    assert "kitchen-cabinets/wall-cabinets" not in slugs
    assert "kitchen-cabinets/base-cabinets" not in slugs
    assert "kitchen-cabinets/anna-stone-gray" in slugs or "kitchen-cabinets/anna-stone-gray-kitchen-cabinets" in slugs
    assert len(slugs) >= 1


def test_intersection_group_paths_include_nested_collection_children(catalog_intent_session):
    session = catalog_intent_session
    from db.channel_listing_path import upsert_listing_path
    from db.listing_intersections import intersection_group_paths_for_hub
    from db.models import MasterTaxonomyNode

    upsert_listing_path(
        session,
        path_slug="kitchen-cabinets",
        title="Kitchen Cabinets",
        path_kind="hub",
        shopping_facet_attribute="cabinet_type",
    )
    upsert_listing_path(
        session,
        path_slug="kitchen-cabinets/wall-cabinets",
        title="Wall Cabinets",
        path_kind="facet",
        hub_path_slug="kitchen-cabinets",
    )
    session.add(
        MasterTaxonomyNode(
            parent_id=None,
            node_kind="collection",
            code="rta-cabinets",
            name="RTA Cabinets",
            path_slug="kitchen-cabinets/rta-cabinets",
        )
    )
    session.add(
        MasterTaxonomyNode(
            parent_id=None,
            node_kind="collection",
            code="rta-cabinets-anna-snow-white",
            name="Anna Snow White",
            path_slug="kitchen-cabinets/rta-cabinets/anna-snow-white",
        )
    )
    session.flush()

    groups = intersection_group_paths_for_hub(session, "kitchen-cabinets")
    slugs = {row["path_slug"] for row in groups}

    assert "kitchen-cabinets/rta-cabinets/anna-snow-white" in slugs
    assert "kitchen-cabinets/wall-cabinets" not in slugs


def test_intersection_group_paths_exclude_shopping_facet_product_taxonomy(catalog_intent_session):
    """accessories/clearance-kit is product L3, not a finish collection for SEO intersections."""
    session = catalog_intent_session
    from db.channel_listing_path import upsert_listing_path
    from db.listing_intersections import intersection_group_paths_for_hub
    from db.models import MasterTaxonomyNode

    upsert_listing_path(
        session,
        path_slug="kitchen-cabinets",
        title="Kitchen Cabinets",
        path_kind="hub",
        shopping_facet_attribute="cabinet_type",
    )
    session.add(
        MasterTaxonomyNode(
            parent_id=None,
            node_kind="collection",
            code="clearance-kit",
            name="Clearance Kit",
            path_slug="kitchen-cabinets/accessories/clearance-kit",
            is_active=True,
        )
    )
    session.add(
        MasterTaxonomyNode(
            parent_id=None,
            node_kind="collection",
            code="anna-snow-white",
            name="Anna Snow White",
            path_slug="kitchen-cabinets/anna-snow-white",
            is_active=True,
        )
    )
    session.flush()

    groups = intersection_group_paths_for_hub(session, "kitchen-cabinets")
    slugs = {row["path_slug"] for row in groups}
    assert "kitchen-cabinets/accessories/clearance-kit" not in slugs
    assert "kitchen-cabinets/anna-snow-white" in slugs


def test_deactivate_shopping_facet_rooted_intersections(catalog_intent_session):
    session = catalog_intent_session
    from db.channel_listing_path import upsert_listing_path, upsert_listing_path_target
    from db.collection_landing_pages import upsert_collection_landing_page
    from db.listing_intersections import deactivate_shopping_facet_rooted_intersections

    bad = upsert_listing_path(
        session,
        path_slug="kitchen-cabinets/accessories/clearance-kit/base-cabinets/double-door-base-cabinet",
        title="Bad SEO",
        path_kind="intersection",
    )
    upsert_listing_path_target(
        session,
        path_slug=bad["path_slug"],
        channel_code="magento",
        remote_id="428",
        taxonomy_kind="category_filter",
        remote_path="kitchen-cabinets/accessories/clearance-kit",
    )
    bad_landing = upsert_collection_landing_page(
        session,
        {
            "path_slug": "kitchen-cabinets/accessories/clearance-kit/base-cabinets",
            "category_l1": "Kitchen Cabinets",
            "collection": "Accessories Clearance Kit Base Cabinets",
            "title": "Kitchen Cabinets / Accessories / Clearance Kit / Base Cabinets",
            "is_active": True,
        },
    )
    good = upsert_listing_path(
        session,
        path_slug="kitchen-cabinets/anna-snow-white/base-cabinets",
        title="Good SEO",
        path_kind="intersection",
    )
    keep_leaf = upsert_listing_path(
        session,
        path_slug="kitchen-cabinets/accessories/clearance-kit",
        title="Clearance Kit",
        path_kind="category",
    )
    session.commit()

    preview = deactivate_shopping_facet_rooted_intersections(session, dry_run=True)
    assert preview["would_deactivate"] >= 1

    applied = deactivate_shopping_facet_rooted_intersections(session, dry_run=False)
    session.commit()
    assert applied["deactivated_paths"] >= 1
    assert applied["deactivated_landings"] >= 1

    from sqlalchemy import select
    from db.models import ChannelListingPath, CollectionLandingPage

    bad_row = session.scalar(
        select(ChannelListingPath).where(ChannelListingPath.path_slug == bad["path_slug"])
    )
    good_row = session.scalar(
        select(ChannelListingPath).where(ChannelListingPath.path_slug == good["path_slug"])
    )
    leaf_row = session.scalar(
        select(ChannelListingPath).where(ChannelListingPath.path_slug == keep_leaf["path_slug"])
    )
    landing_row = session.scalar(
        select(CollectionLandingPage).where(CollectionLandingPage.path_slug == bad_landing["path_slug"])
    )
    assert bad_row is not None and bad_row.is_active is False
    assert good_row is not None and good_row.is_active is True
    assert leaf_row is not None and leaf_row.is_active is True
    assert landing_row is not None and landing_row.is_active is False


def test_intersection_form_options_returns_hub_defaults(catalog_intent_session):
    session = catalog_intent_session
    from db.listing_intersections import intersection_form_options

    upsert_listing_path(
        session,
        path_slug="kitchen-cabinets",
        title="Kitchen Cabinets",
        path_kind="hub",
        shopping_facet_attribute="cabinet_type",
    )

    data = intersection_form_options(session, hub_path_slug="kitchen-cabinets")

    assert any(hub["path_slug"] == "kitchen-cabinets" for hub in data["hubs"])
    assert data["shopping_facet_attribute"] == "cabinet_type"
    assert len(data["facet_options"]) == 5
    assert data["facet_options"][0]["label"] == "Base Cabinets"
    group_slugs = {row["path_slug"] for row in data["groups"]}
    assert "kitchen-cabinets/wall-cabinets" not in group_slugs
    assert "kitchen-cabinets/base-cabinets" not in group_slugs


def test_intersection_form_options_ignores_polluted_kitchen_cabinet_facet_paths(catalog_intent_session):
    session = catalog_intent_session
    from db.listing_intersections import intersection_form_options

    upsert_listing_path(
        session,
        path_slug="kitchen-cabinets",
        title="Kitchen Cabinets",
        path_kind="hub",
        shopping_facet_attribute="cabinet_type",
    )
    for slug, title in (
        ("kitchen-cabinets/caramel-harvest", "Caramel Harvest"),
        ("kitchen-cabinets/metro-frost", "Metro Frost"),
        ("kitchen-cabinets/tall", "Tall"),
    ):
        upsert_listing_path(
            session,
            path_slug=slug,
            title=title,
            path_kind="facet",
            hub_path_slug="kitchen-cabinets",
        )

    data = intersection_form_options(session, hub_path_slug="kitchen-cabinets")
    labels = [row["label"] for row in data["facet_options"]]

    assert labels == ["Base Cabinets", "Wall Cabinets", "Panels and Fillers", "Mouldings", "Accessories"]
    assert {row.get("source") for row in data["facet_options"]} == {"default"}


def test_inferred_collection_page_includes_shopping_intersections(catalog_intent_session):
    session = catalog_intent_session
    from db.collection_landing_pages import get_collection_landing_page
    from db.listing_intersections import sync_shopping_intersections_for_collection

    sync_shopping_intersections_for_collection(
        session,
        {
            "path_slug": "kitchen-cabinets/anna-snow-white",
            "category_l1": "Kitchen Cabinets",
            "collection": "Anna Snow White",
        },
        magento_category_id=501,
    )

    page = get_collection_landing_page(session, "kitchen-cabinets/anna-snow-white")

    assert page is not None
    assert page.get("inferred") is True
    assert len(page.get("shopping_intersections") or []) >= 5
