from __future__ import annotations

from db.manual_variation_assignments import (
    list_manual_variation_assignments,
    replace_manual_variation_assignments,
)
from db.models import MasterCollectionRegistry, MasterProduct, MasterProductRelation


def _product(sku: str, name: str, collection: str = "Anna Caramel Harvest") -> MasterProduct:
    return MasterProduct(
        sku=sku,
        name=name,
        collection=collection,
        status="active",
        row_hash=sku.lower(),
        is_active=True,
    )


def _collection(code: str, name: str, path_slug: str) -> MasterCollectionRegistry:
    return MasterCollectionRegistry(
        code=code,
        name=name,
        path_slug=path_slug,
        is_active=True,
        aliases={"source_collection_code": code, "alias_codes": [code]},
    )


def test_replace_manual_variation_assignments_expands_base_skus_across_selected_collections(catalog_intent_session):
    session = catalog_intent_session
    session.add_all(
        [
            _collection("ACH", "Anna Caramel Harvest", "kitchen-cabinets/anna-caramel-harvest"),
            _collection("ASG", "Anna Stone Gray", "kitchen-cabinets/anna-stone-gray"),
            _product("ACH-B12", "ACH Base 12", "Anna Caramel Harvest"),
            _product("ACH-B15", "ACH Base 15", "Anna Caramel Harvest"),
            _product("ASG-B12", "ASG Base 12", "Anna Stone Gray"),
            _product("ASG-B15", "ASG Base 15", "Anna Stone Gray"),
        ]
    )
    session.commit()

    result = replace_manual_variation_assignments(
        session,
        {
            "templates": [
                {
                    "source_parent_sku": "B-PARENT",
                    "source_parent_name": "Base Cabinet Parent",
                    "group_values": {"product_family": "Cabinets"},
                    "option_attrs": ["variation_width_in"],
                    "collections": [
                        {"collection_code": "ACH"},
                        {"collection_code": "ASG"},
                    ],
                    "children": [
                        {"source_sku": "B12", "name": "Base 12", "option_mapping": {"variation_width_in": "12"}},
                        {"source_sku": "B15", "name": "Base 15", "option_mapping": {"variation_width_in": "15"}},
                    ],
                }
            ],
            "assign_channels": [],
            "create_identity_mappings": False,
        },
    )
    session.commit()

    assert result["saved_template_count"] == 1
    assert result["parents_upserted"] == 2
    assert result["relations_upserted"] == 4

    listed = list_manual_variation_assignments(session)
    assert listed["template_count"] == 1
    template = listed["templates"][0]
    assert template["source_parent_sku"] == "B-PARENT"
    assert template["source_parent_name"] == "Base Cabinet Parent"
    assert sorted(item["collection_code"] for item in template["collections"]) == ["ACH", "ASG"]
    assert [child["source_sku"] for child in template["children"]] == ["B12", "B15"]

    parents = session.query(MasterProduct).filter(MasterProduct.sku.in_(["ACH-B-PARENT", "ASG-B-PARENT"])).all()
    assert len(parents) == 2
    assert all(parent.raw_payload["generated_by"] == "manual_variation" for parent in parents)

    relations = (
        session.query(MasterProductRelation)
        .filter(MasterProductRelation.parent_sku.in_(["ACH-B-PARENT", "ASG-B-PARENT"]))
        .order_by(MasterProductRelation.parent_sku, MasterProductRelation.sort_order)
        .all()
    )
    assert len(relations) == 4
    assert relations[0].source_label == "manual_variation"


def test_replace_manual_variation_assignments_updates_one_base_template_without_touching_others(catalog_intent_session):
    session = catalog_intent_session
    session.add_all(
        [
            _collection("ACH", "Anna Caramel Harvest", "kitchen-cabinets/anna-caramel-harvest"),
            _product("ACH-B12", "ACH Base 12", "Anna Caramel Harvest"),
            _product("ACH-B15", "ACH Base 15", "Anna Caramel Harvest"),
            _product("ACH-W1230", "ACH Wall 12x30", "Anna Caramel Harvest"),
            _product("ACH-W1530", "ACH Wall 15x30", "Anna Caramel Harvest"),
        ]
    )
    session.commit()

    replace_manual_variation_assignments(
        session,
        {
            "templates": [
                {
                    "source_parent_sku": "B-PARENT",
                    "source_parent_name": "Base Parent",
                    "option_attrs": ["variation_width_in"],
                    "collections": [{"collection_code": "ACH"}],
                    "children": [
                        {"source_sku": "B12", "option_mapping": {"variation_width_in": "12"}},
                        {"source_sku": "B15", "option_mapping": {"variation_width_in": "15"}},
                    ],
                }
            ],
            "assign_channels": [],
            "create_identity_mappings": False,
        },
    )
    replace_manual_variation_assignments(
        session,
        {
            "templates": [
                {
                    "source_parent_sku": "W-PARENT",
                    "source_parent_name": "Wall Parent",
                    "option_attrs": ["variation_width_in"],
                    "collections": [{"collection_code": "ACH"}],
                    "children": [
                        {"source_sku": "W1230", "option_mapping": {"variation_width_in": "12"}},
                        {"source_sku": "W1530", "option_mapping": {"variation_width_in": "15"}},
                    ],
                }
            ],
            "assign_channels": [],
            "create_identity_mappings": False,
        },
    )

    updated = replace_manual_variation_assignments(
        session,
        {
            "templates": [
                {
                    "source_parent_sku": "B-PARENT",
                    "source_parent_name": "Base Parent Updated",
                    "option_attrs": ["variation_width_in"],
                    "collections": [{"collection_code": "ACH"}],
                    "children": [
                        {"source_sku": "B12", "option_mapping": {"variation_width_in": "12"}},
                        {"source_sku": "B15", "option_mapping": {"variation_width_in": "15"}},
                    ],
                }
            ],
            "assign_channels": [],
            "create_identity_mappings": False,
        },
    )
    session.commit()

    assert updated["template_count"] == 2
    names = {row["source_parent_sku"]: row["source_parent_name"] for row in updated["templates"]}
    assert names["B-PARENT"] == "Base Parent Updated"
    assert names["W-PARENT"] == "Wall Parent"
