from db.catalog_intent_planner import (
    category_targets_for_product,
    shopify_collection_targets_for_product,
)
from db.channel_catalog_provision import (
    ProvisionOptions,
    build_channel_catalog_plan,
    build_master_listing_path_plan,
)
from db.models import MasterProduct


def _product():
    product = MasterProduct()
    product.sku = "ACH-W2424"
    product.name = "W2424 - Anna Caramel Harvest - Wall"
    product.category_l1 = "Kitchen Cabinets"
    product.category_l2 = "Port & Bell"
    product.category_l3 = None
    product.brand = "Port & Bell"
    product.collection = "Anna Caramel Harvest"
    product.product_family = "Cabinets"
    product.assembly_type = "Assembled"
    product.is_active = True
    return product


def _other_brand_product():
    product = MasterProduct()
    product.id = 2
    product.sku = "CC-W2424"
    product.name = "W2424 - CastleCraft - Wall"
    product.category_l1 = "Kitchen Cabinets"
    product.category_l2 = "CastleCraft"
    product.category_l3 = None
    product.brand = "CastleCraft"
    product.manufacturer = "CastleCraft"
    product.collection = "Shaker White"
    product.product_family = "Cabinets"
    product.assembly_type = "Assembled"
    product.is_active = True
    return product


def test_category_targets_include_all_products_hierarchy_and_collection():
    targets = category_targets_for_product(
        _product(),
        {
            "cabinet_type_sub_category_1": "Base",
            "cabinet_type_sub_category_2": "Single Door Base Cabinet",
        },
    )

    assert targets == [
        "All Products",
        "Kitchen Cabinets",
        "Kitchen Cabinets/Base Cabinets",
        "Kitchen Cabinets/Base Cabinets/Single Door Base Cabinet",
        "Kitchen Cabinets/Anna Caramel Harvest",
        "Anna Caramel Harvest",
    ]


def test_shopify_collection_targets_match_categories_family_and_assembly():
    product = _product()
    targets = shopify_collection_targets_for_product(
        product,
        category_targets_for_product(
            product,
            {
                "cabinet_type_sub_category_1": "Base",
                "cabinet_type_sub_category_2": "Single Door Base Cabinet",
            },
        ),
        {
            "cabinet_type_sub_category_1": "Base",
            "cabinet_type_sub_category_2": "Single Door Base Cabinet",
        },
    )

    assert "All Products" not in targets
    assert "Kitchen Cabinets" in targets
    assert "Base Cabinets" in targets
    assert "Single Door Base Cabinet" in targets
    assert "Anna Caramel Harvest" in targets
    assert "Cabinets" not in targets
    assert "Kitchen Cabinets - Assembled" in targets


def test_shopify_brand_collection_can_be_disabled():
    product = _product()
    attrs = {
        "cabinet_type_sub_category_1": "Base",
        "cabinet_type_sub_category_2": "Single Door Base Cabinet",
    }
    targets = shopify_collection_targets_for_product(
        product,
        category_targets_for_product(product, attrs),
        attrs,
        include_brand=False,
    )

    assert "Port & Bell" not in targets
    assert "Anna Caramel Harvest" in targets


def test_plan_keeps_channel_assignments_separate_and_filters_shopify_brand(monkeypatch):
    port_and_bell = _product()
    port_and_bell.id = 1
    port_and_bell.manufacturer = "Port & Bell"
    castlecraft = _other_brand_product()

    def assigned(_session, channel_code):
        if channel_code == "magento":
            return {"ACH-W2424", "CC-W2424"}
        if channel_code == "shopify":
            return {"ACH-W2424", "CC-W2424"}
        return set()

    monkeypatch.setattr("db.channel_catalog_provision.active_skus_for_channel", assigned)
    monkeypatch.setattr(
        "db.channel_catalog_provision.category_targets_for_product_guarded",
        lambda _session, product, attrs, **kwargs: category_targets_for_product(product, attrs),
    )
    monkeypatch.setattr(
        "db.channel_catalog_provision._attrs_by_sku",
        lambda _session, _ids: {
            "ACH-W2424": {"cabinet_type_sub_category_1": "Wall"},
            "CC-W2424": {"cabinet_type_sub_category_1": "Wall"},
        },
    )
    monkeypatch.setattr("db.channel_catalog_provision._existing_magento_categories", lambda *_args: {})
    monkeypatch.setattr("db.channel_catalog_provision._existing_shopify_collections", lambda *_args: {})
    monkeypatch.setattr("db.channel_catalog_provision._suggest_shopify_category", lambda *_args: None)

    plan = build_channel_catalog_plan(
        object(),
        [port_and_bell, castlecraft],
        options=ProvisionOptions(
            only_assigned=True,
            include_magento=True,
            include_shopify=True,
            delta_only=False,
            shopify_brand_filter=["Port & Bell"],
        ),
    )

    magento_skus = {item["master_sku"] for item in plan["magento"]["assignments"]}
    shopify_skus = {item["master_sku"] for item in plan["shopify"]["collection_assignments"]}

    assert magento_skus == {"ACH-W2424", "CC-W2424"}
    assert shopify_skus == {"ACH-W2424"}
    assert plan["product_counts"] == {"magento": 2, "shopify": 1}


def test_delta_plan_skips_existing_remote_assignments(monkeypatch):
    product = _product()
    product.id = 1
    product.manufacturer = "Port & Bell"

    monkeypatch.setattr("db.channel_catalog_provision.active_skus_for_channel", lambda *_args: {"ACH-W2424"})
    monkeypatch.setattr(
        "db.channel_catalog_provision.category_targets_for_product_guarded",
        lambda _session, product, attrs, **kwargs: category_targets_for_product(product, attrs),
    )
    monkeypatch.setattr(
        "db.channel_catalog_provision._attrs_by_sku",
        lambda _session, _ids: {"ACH-W2424": {"cabinet_type_sub_category_1": "Wall"}},
    )
    monkeypatch.setattr(
        "db.channel_catalog_provision._existing_magento_categories",
        lambda *_args: {"All Products": 2, "Kitchen Cabinets": 3},
    )
    monkeypatch.setattr(
        "db.channel_catalog_provision._existing_shopify_collections",
        lambda *_args: {"kitchen cabinets": "gid://shopify/Collection/10"},
    )
    monkeypatch.setattr(
        "db.channel_catalog_provision._existing_assignment_keys",
        lambda *_args, **_kwargs: {
            ("ACH-W2424", "magento", "category", "2"),
            ("ACH-W2424", "shopify", "collection", "gid://shopify/Collection/10"),
        },
    )
    monkeypatch.setattr("db.channel_catalog_provision._suggest_shopify_category", lambda *_args: None)

    plan = build_channel_catalog_plan(
        object(),
        [product],
        options=ProvisionOptions(
            only_assigned=True,
            include_magento=True,
            include_shopify=True,
            delta_only=True,
            shopify_brand_filter=["Port & Bell"],
        ),
    )

    magento_paths = {item["path"] for item in plan["magento"]["assignments"]}
    shopify_titles = {item["title"] for item in plan["shopify"]["collection_assignments"]}

    assert "All Products" not in magento_paths
    assert "Kitchen Cabinets" in magento_paths
    assert "Kitchen Cabinets" not in shopify_titles


def test_master_listing_path_plan_is_independent_of_channel_assignments(monkeypatch):
    product = _other_brand_product()
    product.sku = "CC-UNASSIGNED"
    product.id = 3

    monkeypatch.setattr(
        "db.channel_catalog_provision.category_targets_for_product_guarded",
        lambda _session, product, attrs, **kwargs: category_targets_for_product(product, attrs),
    )
    monkeypatch.setattr(
        "db.channel_catalog_provision._attrs_by_sku",
        lambda _session, _ids: {
            "CC-UNASSIGNED": {
                "cabinet_type_sub_category_1": "Wall",
                "cabinet_type_sub_category_2": "Glass Door",
            }
        },
    )
    monkeypatch.setattr("db.channel_catalog_provision._existing_listing_paths", lambda _session: {})
    monkeypatch.setattr("db.channel_catalog_provision._existing_listing_assignment_keys", lambda *_args, **_kwargs: set())

    plan = build_master_listing_path_plan(
        object(),
        [product],
        options=ProvisionOptions(only_assigned=True, delta_only=True),
    )

    slugs = {target["path_slug"] for target in plan["path_targets"]}
    assignment_skus = {item["master_sku"] for item in plan["assignments"]}

    assert "kitchen-cabinets" in slugs
    assert "kitchen-cabinets/wall-cabinets" in slugs
    assert "shaker-white" in slugs
    assert assignment_skus == {"CC-UNASSIGNED"}


def test_category_targets_put_collection_under_top_category_without_brand():
    product = _product()
    product.collection = "Anna Stone Grey"
    targets = category_targets_for_product(product, {"cabinet_type_sub_category_1": "Wall"})

    assert "Kitchen Cabinets/Port & Bell" not in targets
    assert "Kitchen Cabinets/Port & Bell/Anna Stone Grey" not in targets
    assert "Kitchen Cabinets/Anna Stone Gray" in targets
    assert "Anna Stone Gray" in targets
