from shopify.collection_sync import assign_product_to_collections
from shopify.smart_collection import evaluate_smart_collection_rules


def test_evaluate_smart_collection_rules_all_must_match():
    rules = {
        "appliedDisjunctively": False,
        "rules": [
            {"column": "VENDOR", "relation": "EQUALS", "condition": "Anna"},
            {"column": "TYPE", "relation": "EQUALS", "condition": "Cabinets"},
        ],
    }
    context = {"vendor": "Anna", "product_type": "Cabinets", "tags": []}

    result = evaluate_smart_collection_rules(rules, context)

    assert result["matches"] is True


def test_evaluate_smart_collection_rules_reports_failed_vendor_rule():
    rules = {
        "appliedDisjunctively": False,
        "rules": [
            {"column": "VENDOR", "relation": "EQUALS", "condition": "Anna"},
        ],
    }
    context = {"vendor": "Home Surplus", "tags": []}

    result = evaluate_smart_collection_rules(rules, context)

    assert result["matches"] is False
    assert result["rule_results"][0]["suggested_action"].startswith("Set vendor")


def test_assign_product_to_collections_skips_smart_collection_manual_add(catalog_intent_session, monkeypatch):
    from datetime import datetime, timezone

    from db.models import ProductChannelTaxonomyAssignment, ShopifyCollectionRegistry, ShopifyConnection

    session = catalog_intent_session
    now = datetime.now(timezone.utc)
    session.add(
        ShopifyConnection(
            id=7,
            shop_code="test",
            shop_domain="test.myshopify.com",
            status="active",
        )
    )
    session.flush()
    smart_id = "gid://shopify/Collection/smart"
    session.add(
        ShopifyCollectionRegistry(
            shop_code="test",
            connection_id=7,
            collection_id=smart_id,
            handle="smart-collection",
            title="Smart Collection",
            collection_type="smart",
            rules_json={
                "appliedDisjunctively": False,
                "rules": [{"column": "TAG", "relation": "EQUALS", "condition": "hardware"}],
            },
            fetched_at=now,
        )
    )
    session.add(
        ProductChannelTaxonomyAssignment(
            master_sku="ACH-B12",
            channel_code="shopify",
            connection_id=7,
            taxonomy_kind="collection",
            remote_id=smart_id,
            assignment_status="active",
        )
    )
    session.flush()
    monkeypatch.setattr(
        "db.product_channel_taxonomy.sku_has_master_taxonomy_placements",
        lambda *_args: True,
    )

    class _Client:
        def graphql(self, query, variables):
            if "query productCollections" in query:
                return {"product": {"collections": {"nodes": []}}}
            raise AssertionError(query)

    result = assign_product_to_collections(
        session,
        _Client(),
        product_id="gid://shopify/Product/1",
        master_sku="ACH-B12",
        fields={"title": "Cabinet", "tags": "base"},
        connection_id=7,
    )

    assert result.collection_ids == [smart_id]
    assert len(result.warnings) == 1
    assert result.warnings[0]["status"] == "rule_mismatch"
    assert "Add product tag 'hardware'" in result.warnings[0]["recommended_actions"][0]


def test_assign_product_to_collections_fetches_smart_type_when_registry_missing(catalog_intent_session, monkeypatch):
    from db.models import ProductChannelTaxonomyAssignment, ShopifyConnection

    session = catalog_intent_session
    session.add(
        ShopifyConnection(
            id=7,
            shop_code="test",
            shop_domain="test.myshopify.com",
            status="active",
        )
    )
    smart_id = "gid://shopify/Collection/smart"
    session.add(
        ProductChannelTaxonomyAssignment(
            master_sku="ACH-B12",
            channel_code="shopify",
            connection_id=7,
            taxonomy_kind="collection",
            remote_id=smart_id,
            assignment_status="active",
        )
    )
    session.flush()
    monkeypatch.setattr(
        "db.product_channel_taxonomy.sku_has_master_taxonomy_placements",
        lambda *_args: True,
    )

    class _Client:
        calls = []

        def graphql(self, query, variables):
            self.calls.append((query, variables))
            if "query productCollections" in query:
                return {"product": {"collections": {"nodes": []}}}
            if "query collectionById" in query:
                return {
                    "collection": {
                        "id": smart_id,
                        "handle": "smart-collection",
                        "title": "Smart Collection",
                        "ruleSet": {
                            "appliedDisjunctively": False,
                            "rules": [{"column": "TAG", "relation": "EQUALS", "condition": "hardware"}],
                        },
                        "productsCount": {"count": 0},
                    }
                }
            if "collectionAddProducts" in query:
                raise AssertionError("should not manually add to smart collection")
            raise AssertionError(query)

    client = _Client()
    result = assign_product_to_collections(
        session,
        client,
        product_id="gid://shopify/Product/1",
        master_sku="ACH-B12",
        fields={"title": "Cabinet", "tags": "base"},
        connection_id=7,
    )

    assert result.collection_ids == [smart_id]
    assert len(result.warnings) == 1
    assert any("collectionById" in query for query, _ in client.calls)
