from __future__ import annotations

from sqlalchemy import select

from db.manual_taxonomy_assignments import (
    list_manual_taxonomy_assignments,
    replace_manual_taxonomy_assignments,
)
from db.models import ManualTaxonomyAssignmentCollection, MasterCollectionRegistry


def test_save_manual_taxonomy_skips_inactive_master_collections(catalog_intent_session):
    session = catalog_intent_session
    active = MasterCollectionRegistry(
        code="ACH",
        name="Anna Caramel Harvest",
        path_slug="kitchen-cabinets/anna-caramel-harvest",
        is_active=True,
        aliases={"source_collection_code": "ACH", "alias_codes": ["ACH"]},
    )
    inactive = MasterCollectionRegistry(
        code="ANNA-CARAMEL-HARVEST",
        name="Kitchen Cabinets / Anna Caramel Harvest",
        path_slug="kitchen-cabinets/anna-caramel-harvest-polluted",
        is_active=False,
        aliases={"source_collection_code": "ANNA-CARAMEL-HARVEST"},
    )
    polluted_active_should_not_matter = MasterCollectionRegistry(
        code="FROST-ACCESSORIES",
        name="Frost - Accessories",
        path_slug="kitchen-cabinets/frost-accessories",
        is_active=False,
    )
    session.add_all([active, inactive, polluted_active_should_not_matter])
    session.flush()

    result = replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "B15",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets/single-door",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Base Cabinets / Single Door",
                    "collections": [
                        {
                            "collection_code": "ACH",
                            "source_collection_code": "ACH",
                            "sku_prefix": "ACH",
                            "collection_name": "Anna Caramel Harvest",
                            "master_sku": "ACH-B15",
                        },
                        {
                            "collection_code": "ANNA-CARAMEL-HARVEST",
                            "source_collection_code": "ANNA-CARAMEL-HARVEST",
                            "sku_prefix": "ANNA-CARAMEL-HARVEST",
                            "collection_name": "Kitchen Cabinets / Anna Caramel Harvest",
                            "master_sku": "ANNA-CARAMEL-HARVEST-B15",
                        },
                        {
                            "collection_code": "FROST-ACCESSORIES",
                            "sku_prefix": "FROST-ACCESSORIES",
                            "collection_name": "Frost - Accessories",
                            "master_sku": "FROST-ACCESSORIES-B15",
                        },
                        {
                            "collection_code": "ACH",
                            "sku_prefix": "ACH",
                            "collection_name": "Anna Caramel Harvest duplicate",
                            "master_sku": "ACH-B15-DUP",
                        },
                    ],
                }
            ]
        },
    )

    assert result["saved_rule_count"] == 1
    assert result["saved_assignment_count"] == 1
    assert result["skipped_inactive_or_unknown_count"] == 2
    assert result["skipped_duplicate_count"] == 1

    rows = session.scalars(select(ManualTaxonomyAssignmentCollection)).all()
    assert len(rows) == 1
    assert rows[0].collection_code == "ACH"
    assert rows[0].collection_registry_id == active.id

    listed = list_manual_taxonomy_assignments(session)
    assert len(listed["assignments"]) == 1
    assert listed["assignments"][0]["collection_code"] == "ACH"


def test_save_manual_taxonomy_does_not_create_unknown_codes(catalog_intent_session):
    session = catalog_intent_session
    result = replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "B12",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets",
                    "collections": [
                        {
                            "collection_code": "NOT-A-REAL-COLLECTION",
                            "sku_prefix": "NOT-A-REAL-COLLECTION",
                            "master_sku": "NOT-A-REAL-COLLECTION-B12",
                        }
                    ],
                }
            ]
        },
    )
    assert result["saved_rule_count"] == 1
    assert result["saved_assignment_count"] == 0
    assert result["skipped_inactive_or_unknown_count"] == 1
    assert session.scalars(select(ManualTaxonomyAssignmentCollection)).all() == []


def test_save_manual_taxonomy_upserts_touched_rule_without_deleting_other_rules(catalog_intent_session):
    session = catalog_intent_session
    session.add_all(
        [
            MasterCollectionRegistry(
                code="ACH",
                name="Anna Caramel Harvest",
                path_slug="kitchen-cabinets/anna-caramel-harvest",
                is_active=True,
                aliases={"source_collection_code": "ACH", "alias_codes": ["ACH"]},
            ),
            MasterCollectionRegistry(
                code="ASG",
                name="Anna Stone Gray",
                path_slug="kitchen-cabinets/anna-stone-gray",
                is_active=True,
                aliases={"source_collection_code": "ASG", "alias_codes": ["ASG"]},
            ),
        ]
    )
    session.flush()

    replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "B12",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets/single-door",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Base Cabinets / Single Door",
                    "shopping_l1": "base-cabinets",
                    "shopping_l2": "base-cabinets/single-door",
                    "l2_category": "Base Cabinets",
                    "l3_category": "Single Door",
                    "collections": [
                        {
                            "collection_code": "ACH",
                            "source_collection_code": "ACH",
                            "sku_prefix": "ACH",
                            "collection_name": "Anna Caramel Harvest",
                            "master_sku": "ACH-B12",
                        }
                    ],
                }
            ]
        },
    )
    replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "W0930",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/wall-cabinets/basic-wall",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Wall Cabinets / Basic Wall",
                    "shopping_l1": "wall-cabinets",
                    "shopping_l2": "wall-cabinets/basic-wall",
                    "l2_category": "Wall Cabinets",
                    "l3_category": "Basic Wall",
                    "collections": [
                        {
                            "collection_code": "ASG",
                            "source_collection_code": "ASG",
                            "sku_prefix": "ASG",
                            "collection_name": "Anna Stone Gray",
                            "master_sku": "ASG-W0930",
                        }
                    ],
                }
            ]
        },
    )

    listed = list_manual_taxonomy_assignments(session)
    assert sorted(item["master_sku"] for item in listed["assignments"]) == ["ACH-B12", "ASG-W0930"]

    updated = replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "B12",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets/sink-base",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Base Cabinets / Sink Base",
                    "shopping_l1": "base-cabinets",
                    "shopping_l2": "base-cabinets/sink-base",
                    "l2_category": "Base Cabinets",
                    "l3_category": "Sink Base",
                    "collections": [
                        {
                            "collection_code": "ACH",
                            "source_collection_code": "ACH",
                            "sku_prefix": "ACH",
                            "collection_name": "Anna Caramel Harvest",
                            "master_sku": "ACH-B12",
                        }
                    ],
                }
            ]
        },
    )

    listed = list_manual_taxonomy_assignments(session)
    by_master_sku = {item["master_sku"]: item for item in listed["assignments"]}
    assert sorted(by_master_sku) == ["ACH-B12", "ASG-W0930"]
    assert by_master_sku["ACH-B12"]["canonical_taxonomy_path_slug"] == "kitchen-cabinets/base-cabinets/sink-base"
    assert by_master_sku["ASG-W0930"]["canonical_taxonomy_path_slug"] == "kitchen-cabinets/wall-cabinets/basic-wall"

    by_template = {
        (item["source_sku"], item["canonical_taxonomy_path_slug"]): item
        for item in listed["templates"]
    }
    assert ("B12", "kitchen-cabinets/base-cabinets/sink-base") in by_template
    assert ("B12", "kitchen-cabinets/base-cabinets/single-door") not in by_template
    assert ("W0930", "kitchen-cabinets/wall-cabinets/basic-wall") in by_template
    assert updated["changed_master_skus"] == ["ACH-B12"]


def test_save_manual_taxonomy_updates_existing_key_in_place(catalog_intent_session):
    session = catalog_intent_session
    session.add(
        MasterCollectionRegistry(
            code="ACH",
            name="Anna Caramel Harvest",
            path_slug="kitchen-cabinets/anna-caramel-harvest",
            is_active=True,
            aliases={"source_collection_code": "ACH", "alias_codes": ["ACH"]},
        )
    )
    session.flush()

    replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "B12",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets/single-door",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Base Cabinets / Single Door",
                    "shopping_l1": "base-cabinets",
                    "shopping_l2": "base-cabinets/single-door",
                    "l2_category": "Base Cabinets",
                    "l3_category": "Single Door",
                    "collections": [
                        {
                            "collection_code": "ACH",
                            "source_collection_code": "ACH",
                            "sku_prefix": "ACH",
                            "collection_name": "Anna Caramel Harvest",
                            "master_sku": "ACH-B12",
                        }
                    ],
                }
            ]
        },
    )

    updated = replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "B12",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets/single-door",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Base Cabinets / Single Door Updated",
                    "shopping_l1": "base-cabinets",
                    "shopping_l2": "base-cabinets/single-door-updated",
                    "l2_category": "Base Cabinets",
                    "l3_category": "Single Door Updated",
                    "collections": [
                        {
                            "collection_code": "ACH",
                            "source_collection_code": "ACH",
                            "sku_prefix": "ACH",
                            "collection_name": "Anna Caramel Harvest",
                            "master_sku": "ACH-B12",
                        }
                    ],
                }
            ]
        },
    )

    listed = list_manual_taxonomy_assignments(session)
    matching_templates = [
        item
        for item in listed["templates"]
        if item["source_sku"] == "B12"
        and item["canonical_taxonomy_path_slug"] == "kitchen-cabinets/base-cabinets/single-door"
    ]
    assert len(matching_templates) == 1
    assert matching_templates[0]["canonical_taxonomy_path_label"] == "Kitchen Cabinets / Base Cabinets / Single Door Updated"
    assert matching_templates[0]["shopping_l2"] == "base-cabinets/single-door-updated"
    assert matching_templates[0]["l3_category"] == "Single Door Updated"
    assert updated["changed_master_skus"] == ["ACH-B12"]


def test_save_manual_taxonomy_last_duplicate_source_sku_wins_without_duplicate_children(catalog_intent_session):
    session = catalog_intent_session
    session.add_all(
        [
            MasterCollectionRegistry(
                code="ACH",
                name="Anna Caramel Harvest",
                path_slug="kitchen-cabinets/anna-caramel-harvest",
                is_active=True,
                aliases={"source_collection_code": "ACH", "alias_codes": ["ACH"]},
            ),
            MasterCollectionRegistry(
                code="ASG",
                name="Anna Stone Gray",
                path_slug="kitchen-cabinets/anna-stone-gray",
                is_active=True,
                aliases={"source_collection_code": "ASG", "alias_codes": ["ASG"]},
            ),
        ]
    )
    session.flush()

    result = replace_manual_taxonomy_assignments(
        session,
        {
            "templates": [
                {
                    "source_sku": "B12",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets/single-door",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Base Cabinets / Single Door",
                    "collections": [
                        {
                            "collection_code": "ACH",
                            "source_collection_code": "ACH",
                            "sku_prefix": "ACH",
                            "collection_name": "Anna Caramel Harvest",
                            "master_sku": "ACH-B12",
                        }
                    ],
                },
                {
                    "source_sku": "B12",
                    "canonical_taxonomy_path_slug": "kitchen-cabinets/base-cabinets/sink-base",
                    "canonical_taxonomy_path_label": "Kitchen Cabinets / Base Cabinets / Sink Base",
                    "collections": [
                        {
                            "collection_code": "ASG",
                            "source_collection_code": "ASG",
                            "sku_prefix": "ASG",
                            "collection_name": "Anna Stone Gray",
                            "master_sku": "ASG-B12",
                        }
                    ],
                },
            ]
        },
    )

    listed = list_manual_taxonomy_assignments(session)
    assert result["saved_rule_count"] == 1
    assert result["saved_assignment_count"] == 1
    assert sorted(item["master_sku"] for item in listed["assignments"]) == ["ASG-B12"]
    assert [
        (item["source_sku"], item["canonical_taxonomy_path_slug"])
        for item in listed["templates"]
    ] == [
        ("B12", "kitchen-cabinets/base-cabinets/sink-base"),
    ]
