from db.collection_landing_pages import get_collection_landing_page, upsert_collection_landing_page
from db.collection_landing_schema import (
    build_channel_field_payload,
    magento_attribute_code,
    serialize_field_value,
    shopify_metafield_key,
)
from db.models import CollectionCommerceProfile, MasterProduct, MasterProductAttributeValue, MasterProductLocationAvailability
from magento.collection_landing_push import build_magento_category_custom_attributes
from shopify.collection_landing_push import push_shopify_collection_landing


def test_build_channel_field_payload_serializes_lists():
    payload = build_channel_field_payload(
        {
            "brand": "Port & Bell",
            "hero_images": ["https://a/1.jpg", "https://a/2.jpg"],
            "feature_bullets": ["Grab & Go"],
            "starting_price": 1156.0,
            "compare_at_price": 1299.0,
            "category_icon_url": "https://a/icon.png",
        }
    )
    assert payload["brand"] == "Port & Bell"
    assert '"https://a/1.jpg"' in (payload["hero_images"] or "")
    assert payload["feature_bullets"] == '["Grab & Go"]'
    assert payload["starting_price"] == "1156.0"
    assert payload["compare_at_price"] == "1299.0"
    assert payload["category_icon_url"] == "https://a/icon.png"


def test_build_channel_field_payload_serializes_sample_and_availability():
    payload = build_channel_field_payload(
        {
            "sample_product": {"master_sku": "EOB-SD", "channel_sku": "EOB-SD", "sku": "EOB-SD", "name": "Sample Door"},
            "availability_filters": [{"label": "Grab & Go", "value": "grab_and_go", "count": 4}],
            "landing_metadata": {"kitchen_packages": [{"code": "l_shape_8x10", "price": 3116}]},
        }
    )
    assert '"EOB-SD"' in (payload["sample_product"] or "")
    assert '"Grab & Go"' in (payload["availability_filters"] or "")
    assert '3116' in (payload["landing_metadata"] or "")


def test_collection_landing_infers_order_sample_cta_and_availability(catalog_intent_session):
    session = catalog_intent_session
    product = MasterProduct(
        sku="EOB-B15",
        name="B15 - Eleanor Ocean Blue",
        category_l1="Kitchen Cabinets",
        collection="Eleanor Ocean Blue",
        row_hash="h-eob-b15",
        is_active=True,
    )
    sample = MasterProduct(
        sku="EOB-SD",
        name="SD - Eleanor Ocean Blue - Port & Bell - Sample Door",
        category_l1="Kitchen Cabinets",
        collection="Eleanor Ocean Blue",
        row_hash="h-eob-sd",
        is_active=True,
    )
    session.add_all([product, sample])
    session.flush()
    session.add(
        MasterProductAttributeValue(
            product_id=product.id,
            sku=product.sku,
            attribute_code="collection_availability",
            value="Grab & Go",
        )
    )
    session.add(
        MasterProductLocationAvailability(
            product_id=product.id,
            sku=product.sku,
            location_code="store",
            is_available=True,
        )
    )
    upsert_collection_landing_page(
        session,
        {
            "path_slug": "kitchen-cabinets/eleanor-ocean-blue",
            "category_l1": "Kitchen Cabinets",
            "collection": "Eleanor Ocean Blue",
            "title": "Eleanor Ocean Blue",
        },
    )
    page = get_collection_landing_page(session, "kitchen-cabinets/eleanor-ocean-blue")
    assert page["sample_product"]["sku"] == "EOB-SD"
    assert page["sample_product"]["master_sku"] == "EOB-SD"
    assert page["sample_product"]["channel_sku"] == "EOB-SD"
    assert any(row.get("action") == "order_sample" and row.get("sku") == "EOB-SD" for row in page["cta_rows"])
    labels = {row["label"] for row in page["availability_filters"]}
    assert {"Grab & Go", "Available"}.issubset(labels)


def test_collection_landing_prefers_normalized_commerce_profile(catalog_intent_session):
    session = catalog_intent_session
    product = MasterProduct(
        sku="ASW-B15",
        name="B15 - Anna Snow White",
        category_l1="Kitchen Cabinets",
        collection="Anna Snow White",
        row_hash="h-asw-b15",
        is_active=True,
    )
    sample = MasterProduct(
        sku="ASW-SD",
        name="Anna Snow White Sample Door",
        category_l1="Kitchen Cabinets",
        collection="Anna Snow White",
        row_hash="h-asw-sd",
        is_active=True,
    )
    session.add_all([product, sample])
    session.flush()
    session.add(
        CollectionCommerceProfile(
            category_l1="Kitchen Cabinets",
            collection_name="Anna Snow White",
            sample_master_sku="ASW-SD",
            sample_category_path_slug="product-category/sample_doors",
            availability_modes_json={"modes": ["special_order"]},
            appointment_url="https://www.homesurplus.com/shaker-white/",
            sample_cta_label="Order Sample",
            appointment_cta_label="Book Appointment",
            landing_metadata_json={"kitchen_packages": [{"code": "l_shape_8x10", "price": 3116}]},
            is_active=True,
        )
    )
    upsert_collection_landing_page(
        session,
        {
            "path_slug": "kitchen-cabinets/anna-snow-white",
            "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["sample_product"]["sku"] == "ASW-SD"
    assert page["sample_product"]["sample_category_path_slug"] == "product-category/sample_doors"
    assert any(row.get("action") == "book_appointment" for row in page["cta_rows"])
    availability_values = {row["value"] for row in page["availability_filters"]}
    assert "special_order" in availability_values
    assert page["landing_metadata"]["kitchen_packages"][0]["price"] == 3116


def test_magento_attribute_codes_prefixed():
    assert magento_attribute_code("hero_images") == "hs_hero_images"


def test_shopify_metafield_keys_match_schema():
    assert shopify_metafield_key("pdf_url") == "pdf_url"


def test_serialize_field_value_skips_empty():
    assert serialize_field_value("badges", []) is None
    assert serialize_field_value("badges", {"badges": [], "availability_locations": []}) is None


def test_normalize_and_serialize_structured_badges():
    from db.collection_landing_schema import normalize_collection_badges

    structured = {
        "badges": ["Grab & Go", "Available in 7 Days", "Special Order"],
        "availability_locations": [
            {
                "badge": "Grab & Go",
                "locations": ["Keyport", "North Bergen", "Bellmawr"],
                "meaning": "Take home today",
            },
            {
                "badge": "Available in 7 Days",
                "locations": ["Brentwood", "Baltimore"],
                "meaning": "Available in 7 days or less",
            },
            {
                "badge": "Special Order",
                "locations": "not location-specific in brochure",
                "meaning": "Additional items not shown above may be available for special order",
            },
        ],
    }
    normalized = normalize_collection_badges(structured)
    assert normalized == structured
    assert normalize_collection_badges(["Grab & Go"]) == {
        "badges": ["Grab & Go"],
        "availability_locations": [],
    }
    assert normalize_collection_badges({"items": ["Grab & Go"]}) == {
        "badges": ["Grab & Go"],
        "availability_locations": [],
    }
    payload = build_channel_field_payload({"badges": structured})
    assert '"availability_locations"' in (payload["badges"] or "")
    assert '"Grab & Go"' in (payload["badges"] or "")
    assert '"Keyport"' in (payload["badges"] or "")


def test_upsert_persists_structured_badges(catalog_intent_session):
    session = catalog_intent_session
    upsert_collection_landing_page(
        session,
        {
            "path_slug": "kitchen-cabinets/galaxy-horizon",
            "category_l1": "Kitchen Cabinets",
            "collection": "Galaxy Horizon",
            "title": "Galaxy Horizon",
            "badges": {
                "badges": ["Grab & Go"],
                "availability_locations": [
                    {
                        "badge": "Grab & Go",
                        "locations": ["Keyport"],
                        "meaning": "Take home today",
                    }
                ],
            },
        },
    )
    page = get_collection_landing_page(session, "kitchen-cabinets/galaxy-horizon")
    assert page["badges"]["badges"] == ["Grab & Go"]
    assert page["badges"]["availability_locations"][0]["locations"] == ["Keyport"]


def test_upsert_collection_save_cleans_pasted_json_escape_artifacts(catalog_intent_session):
    session = catalog_intent_session
    upsert_collection_landing_page(
        session,
        {
            "path_slug": "kitchen-cabinets/anna-caramel-harvest",
            "category_l1": "Kitchen Cabinets",
            "collection": "Anna Caramel Harvest",
            "title": "Anna Caramel Harvest",
            "short_description": '"Premium shaker-style stained birch cabinet line with warm modern look.\\nSecond line."',
            "description_html": '<p>Line one</p>\\n<ul><li>Line two</li></ul>\\",\\n    \\"specifications_html\\": \\"<ul><li>Wrong place</li></ul>',
            "specifications_html": '<ul>\\n  <li><strong>Door Style:</strong> Shaker</li>\\n</ul>',
        },
    )
    page = get_collection_landing_page(session, "kitchen-cabinets/anna-caramel-harvest")
    assert page["short_description"] == "Premium shaker-style stained birch cabinet line with warm modern look.\nSecond line."
    assert page["description_html"] == "<p>Line one</p>\n<ul><li>Line two</li></ul>"
    assert page["specifications_html"] == "<ul>\n  <li><strong>Door Style:</strong> Shaker</li>\n</ul>"


def test_serialize_boolean_relationship_fields_for_channel_apis():
    assert serialize_field_value("is_collection", True) == "true"
    assert serialize_field_value("has_collections", False) == "false"


def test_magento_relationship_booleans_use_eav_integer_values():
    attrs = build_magento_category_custom_attributes(
        {"is_collection": True, "has_collections": False},
        field_keys={"is_collection", "has_collections"},
    )
    values = {item["attribute_code"]: item["value"] for item in attrs}
    assert values == {"hs_is_collection": "1", "hs_has_collections": "0"}


def test_shopify_collection_metafields_are_batched_at_25():
    class Client:
        def __init__(self):
            self.batch_sizes = []

        def graphql(self, _query, variables):
            if "input" in variables:
                return {"collectionUpdate": {"collection": variables["input"], "userErrors": []}}
            batch = variables["metafields"]
            self.batch_sizes.append(len(batch))
            return {"metafieldsSet": {"metafields": batch, "userErrors": []}}

    client = Client()
    row = {
        "brand": "Port & Bell",
        "subtitle": "Collection",
        "short_description": "Description",
        "thumbnail_image_url": "https://cdn.shopify.com/files/image.jpg",
        "pdf_url": "https://cdn.shopify.com/files/info.pdf",
        "starting_price": 10,
        "compare_at_price": 12,
        "category_icon_url": "https://cdn.shopify.com/files/icon.png",
        "hero_images": ["https://cdn.shopify.com/files/hero.jpg"],
        "badges": ["New"],
        "feature_bullets": ["Feature"],
        "cta_rows": [{"label": "Shop"}],
        "matching_collection_slugs": ["kitchen-cabinets/white"],
        "sku_prefixes": ["ASG"],
        "description_html": "<p>Description</p>",
        "specifications_html": "<p>Specs</p>",
        "materials_html": "<p>Materials</p>",
        "assembly_html": "<p>Assembly</p>",
        "is_collection": True,
        "has_collections": False,
        "taxonomy_path_slug": "kitchen-cabinets/anna-stone-gray",
        "parent_path_slug": "kitchen-cabinets",
        "parent_remote_id": "gid://shopify/Collection/1",
        "child_remote_ids": ["gid://shopify/Collection/4"],
        "sibling_remote_ids": ["gid://shopify/Collection/2"],
        "child_taxonomy_nodes": [{"name": "Child"}],
        "sibling_taxonomy_nodes": [{"name": "Base Cabinets"}],
    }

    with patch(
        "shopify.collection_landing_push.localize_shopify_collection_assets",
        return_value=(row, []),
    ):
        result = push_shopify_collection_landing(
            client,
            collection_gid="gid://shopify/Collection/3",
            collection_row=row,
        )

    assert client.batch_sizes == [25, 3]
    assert result["pushed"] == 28
from unittest.mock import patch
