from db.models import MasterProduct, MasterProductAttributeValue, MasterProductRelation
from db.variation_builder import (
    export_variation_parent_child_rows,
    repair_variation_relations_from_payload,
)


def test_export_variation_parents_uses_relations_and_option_mapping(catalog_intent_session):
    parent = MasterProduct(
        sku="ACH-B-PARENT",
        name="Anna Caramel Harvest Base",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="parent",
        raw_payload={
            "generated_by": "variation_builder",
            "option_attrs": ["variation_width_in", "variation_option_label"],
            "children": ["ACH-B12", "ACH-B15"],
            "group_values": {"collection": "Anna Caramel Harvest"},
        },
        is_active=True,
    )
    child_1 = MasterProduct(
        sku="ACH-B12",
        name="B12",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="c1",
        is_active=True,
    )
    child_2 = MasterProduct(
        sku="ACH-B15",
        name="B15",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="c2",
        is_active=True,
    )
    catalog_intent_session.add_all([parent, child_1, child_2])
    catalog_intent_session.flush()
    catalog_intent_session.add_all(
        [
            MasterProductAttributeValue(
                product_id=child_1.id,
                sku=child_1.sku,
                attribute_code="variation_width_in",
                value="12",
            ),
            MasterProductAttributeValue(
                product_id=child_2.id,
                sku=child_2.sku,
                attribute_code="variation_width_in",
                value="15",
            ),
            MasterProductRelation(
                parent_sku=parent.sku,
                child_sku=child_1.sku,
                option_mapping={"variation_width_in": "12", "variation_option_label": "12 in W"},
                sort_order=0,
                source_label="variation_builder",
            ),
            MasterProductRelation(
                parent_sku=parent.sku,
                child_sku=child_2.sku,
                option_mapping={"variation_width_in": "15", "variation_option_label": "15 in W"},
                sort_order=1,
                source_label="variation_builder",
            ),
        ]
    )
    catalog_intent_session.commit()

    result = export_variation_parent_child_rows(catalog_intent_session)
    assert result["parent_count"] == 1
    assert result["child_count"] == 2
    assert result["option_attrs"] == ["variation_width_in"]
    by_child = {row["child_sku"]: row for row in result["rows"]}
    assert by_child["ACH-B12"]["parent_sku"] == "ACH-B-PARENT"
    assert by_child["ACH-B12"]["variation_width_in"] == "12"
    assert by_child["ACH-B12"]["option_label"] == "Width"
    assert by_child["ACH-B12"]["magento_configurable_attributes"] == "width"
    assert by_child["ACH-B12"]["variant_of"] == "ACH-B-PARENT"
    assert "ACH-B12" in by_child["ACH-B12"]["variant_list"]
    assert "width=12" in by_child["ACH-B12"]["configurable_variations"]
    assert by_child["ACH-B12"]["link_source"] == "relation"
    assert "variation_option_label" not in by_child["ACH-B12"]


def test_export_variation_parents_falls_back_to_raw_payload_children(catalog_intent_session):
    parent = MasterProduct(
        sku="ACH-SB-PARENT",
        name="Anna Caramel Harvest Sink",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="parent",
        raw_payload={
            "generated_by": "variation_builder",
            "option_attrs": ["variation_width_in", "variation_option_label"],
            "children": ["ACH-SB36"],
            "group_values": {"collection": "Anna Caramel Harvest"},
            "explicit_seo_title": True,
        },
        is_active=True,
    )
    child = MasterProduct(
        sku="ACH-SB36",
        name="SB36",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="c1",
        is_active=True,
    )
    catalog_intent_session.add_all([parent, child])
    catalog_intent_session.flush()
    catalog_intent_session.add(
        MasterProductAttributeValue(
            product_id=child.id,
            sku=child.sku,
            attribute_code="variation_width_in",
            value="36",
        )
    )
    catalog_intent_session.commit()

    result = export_variation_parent_child_rows(catalog_intent_session, parent_skus=["ACH-SB-PARENT"])
    assert result["parent_count"] == 1
    assert result["child_count"] == 1
    row = result["rows"][0]
    assert row["parent_sku"] == "ACH-SB-PARENT"
    assert row["child_sku"] == "ACH-SB36"
    assert row["link_source"] == "raw_payload"
    assert row["option_attrs"] == "variation_width_in"
    assert row["option_label"] == "Width"
    assert row["variation_width_in"] == "36"
    assert row["explicit_seo_title"] is True


def test_repair_variation_relations_backfills_from_raw_payload(catalog_intent_session):
    parent = MasterProduct(
        sku="ACH-B-PARENT",
        name="Anna Caramel Harvest Base",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="parent",
        raw_payload={
            "generated_by": "variation_builder",
            "option_attrs": ["variation_width_in", "variation_option_label"],
            "children": ["ACH-B12", "ACH-B15"],
            "group_values": {"collection": "Anna Caramel Harvest"},
        },
        is_active=True,
    )
    child_1 = MasterProduct(
        sku="ACH-B12",
        name="B12",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="c1",
        is_active=True,
    )
    child_2 = MasterProduct(
        sku="ACH-B15",
        name="B15",
        collection="Anna Caramel Harvest",
        status="active",
        row_hash="c2",
        is_active=True,
    )
    catalog_intent_session.add_all([parent, child_1, child_2])
    catalog_intent_session.flush()
    catalog_intent_session.add_all(
        [
            MasterProductAttributeValue(
                product_id=child_1.id,
                sku=child_1.sku,
                attribute_code="variation_width_in",
                value="12",
            ),
            MasterProductAttributeValue(
                product_id=child_2.id,
                sku=child_2.sku,
                attribute_code="variation_width_in",
                value="15",
            ),
        ]
    )
    catalog_intent_session.commit()

    result = repair_variation_relations_from_payload(catalog_intent_session)
    catalog_intent_session.commit()

    assert result["relations_upserted"] == 2
    assert result["payloads_cleaned"] == 1
    assert parent.raw_payload["option_attrs"] == ["variation_width_in"]

    relations = (
        catalog_intent_session.query(MasterProductRelation)
        .filter_by(parent_sku="ACH-B-PARENT")
        .order_by(MasterProductRelation.sort_order)
        .all()
    )
    assert len(relations) == 2
    assert relations[0].child_sku == "ACH-B12"
    assert relations[0].option_mapping == {"variation_width_in": "12"}
    assert relations[1].option_mapping == {"variation_width_in": "15"}

    export = export_variation_parent_child_rows(catalog_intent_session, parent_skus=["ACH-B-PARENT"])
    assert export["rows"][0]["link_source"] == "relation"
    assert export["rows"][0]["option_label"] == "Width"
    assert "sku=ACH-B12,width=12" in export["rows"][0]["configurable_variations"]


def test_repair_variation_relations_expands_existing_width_only_mapping(catalog_intent_session):
    parent = MasterProduct(
        sku="MBRO-VSD-PARENT",
        name="Maya Vanity",
        collection="Maya Black Rift White Oak",
        status="active",
        row_hash="parent-vsd",
        raw_payload={
            "generated_by": "variation_builder",
            "option_attrs": ["variation_width_in"],
            "children": ["MBRO-VSD3021DL", "MBRO-VSD3021DR", "MBRO-VSD3621DL", "MBRO-VSD3621DR"],
            "group_values": {"collection": "Maya Black Rift White Oak"},
        },
        is_active=True,
    )
    child_left = MasterProduct(
        sku="MBRO-VSD3021DL",
        name="Vanity 30 Left",
        collection="Maya Black Rift White Oak",
        status="active",
        row_hash="vsd-left",
        is_active=True,
    )
    child_right = MasterProduct(
        sku="MBRO-VSD3021DR",
        name="Vanity 30 Right",
        collection="Maya Black Rift White Oak",
        status="active",
        row_hash="vsd-right",
        is_active=True,
    )
    child_left_36 = MasterProduct(
        sku="MBRO-VSD3621DL",
        name="Vanity 36 Left",
        collection="Maya Black Rift White Oak",
        status="active",
        row_hash="vsd-left-36",
        is_active=True,
    )
    child_right_36 = MasterProduct(
        sku="MBRO-VSD3621DR",
        name="Vanity 36 Right",
        collection="Maya Black Rift White Oak",
        status="active",
        row_hash="vsd-right-36",
        is_active=True,
    )
    catalog_intent_session.add_all([parent, child_left, child_right, child_left_36, child_right_36])
    catalog_intent_session.flush()
    catalog_intent_session.add_all(
        [
            MasterProductAttributeValue(
                product_id=child_left.id,
                sku=child_left.sku,
                attribute_code="variation_width_in",
                value="30",
            ),
            MasterProductAttributeValue(
                product_id=child_right.id,
                sku=child_right.sku,
                attribute_code="variation_width_in",
                value="30",
            ),
            MasterProductAttributeValue(
                product_id=child_left_36.id,
                sku=child_left_36.sku,
                attribute_code="variation_width_in",
                value="36",
            ),
            MasterProductAttributeValue(
                product_id=child_right_36.id,
                sku=child_right_36.sku,
                attribute_code="variation_width_in",
                value="36",
            ),
            MasterProductRelation(
                parent_sku=parent.sku,
                child_sku=child_left.sku,
                option_mapping={"variation_width_in": "30"},
                sort_order=0,
                source_label="legacy_width_only",
            ),
            MasterProductRelation(
                parent_sku=parent.sku,
                child_sku=child_right.sku,
                option_mapping={"variation_width_in": "30"},
                sort_order=1,
                source_label="legacy_width_only",
            ),
            MasterProductRelation(
                parent_sku=parent.sku,
                child_sku=child_left_36.sku,
                option_mapping={"variation_width_in": "36"},
                sort_order=2,
                source_label="legacy_width_only",
            ),
            MasterProductRelation(
                parent_sku=parent.sku,
                child_sku=child_right_36.sku,
                option_mapping={"variation_width_in": "36"},
                sort_order=3,
                source_label="legacy_width_only",
            ),
        ]
    )
    catalog_intent_session.commit()

    result = repair_variation_relations_from_payload(
        catalog_intent_session,
        parent_skus=[parent.sku],
    )
    catalog_intent_session.commit()

    assert result["relations_upserted"] == 4
    assert parent.raw_payload["option_attrs"] == [
        "variation_width_in",
        "variation_door_handing",
        "variation_variant_code",
    ]

    relations = (
        catalog_intent_session.query(MasterProductRelation)
        .filter_by(parent_sku=parent.sku)
        .order_by(MasterProductRelation.sort_order)
        .all()
    )
    assert relations[0].option_mapping == {
        "variation_width_in": "30",
        "variation_door_handing": "Left",
        "variation_variant_code": "21DL",
    }
    assert relations[1].option_mapping == {
        "variation_width_in": "30",
        "variation_door_handing": "Right",
        "variation_variant_code": "21DR",
    }
    assert relations[2].option_mapping == {
        "variation_width_in": "36",
        "variation_door_handing": "Left",
        "variation_variant_code": "21DL",
    }
    assert relations[3].option_mapping == {
        "variation_width_in": "36",
        "variation_door_handing": "Right",
        "variation_variant_code": "21DR",
    }
