from __future__ import annotations

import pandas as pd
from sqlalchemy import select

from db.manual_attributes import (
    DEFAULT_MANUAL_ATTRIBUTES,
    ensure_default_manual_attributes,
    list_manual_attributes,
    locked_values_for_code,
    replace_manual_attributes,
)
from db.master_catalog import import_master_sku_dataframe
from db.master_product_filters import list_master_attribute_values
from db.models import MasterProduct, MasterProductAttributeValue


def test_ensure_default_manual_attributes_seeds_assembled_or_rta(catalog_intent_session):
    session = catalog_intent_session
    result = ensure_default_manual_attributes(session)
    assert result["seeded_count"] == 1
    assert result["count"] == 1
    attr = result["attributes"][0]
    assert attr["attribute_code"] == "assembled_or_rta"
    assert attr["is_locked"] is True
    assert [item["value"] for item in attr["values"]] == ["Assembled", "Unassembled/RTA"]

    again = ensure_default_manual_attributes(session)
    assert again["seeded_count"] == 0
    assert again["count"] == 1


def test_replace_manual_attributes_upserts_values(catalog_intent_session):
    session = catalog_intent_session
    result = replace_manual_attributes(
        session,
        {
            "attributes": [
                {
                    "attribute_code": "color_family",
                    "label": "Color Family",
                    "is_locked": True,
                    "unknown_policy": "drop",
                    "values": [
                        {"value": "Brown", "aliases": ["brown", "espresso"]},
                        {"value": "White", "aliases": ["white", "pearl"]},
                    ],
                }
            ]
        },
    )
    assert result["saved_count"] == 1
    assert result["attributes"][0]["attribute_code"] == "color_family"
    assert locked_values_for_code(session, "color_family") == ["Brown", "White"]


def test_list_master_attribute_values_uses_locked_vocabulary(catalog_intent_session):
    session = catalog_intent_session
    ensure_default_manual_attributes(session)
    # Pollute DB with junk distincts — locked vocab must hide them.
    product = MasterProduct(sku="ACH-B12", name="B12", assembly_type="bundle", is_active=True, row_hash="x")
    session.add(product)
    session.flush()
    session.add(
        MasterProductAttributeValue(
            product_id=product.id,
            sku=product.sku,
            attribute_code="assembled_or_rta",
            value="bundle",
            source_label="test",
        )
    )
    session.flush()

    values = list_master_attribute_values(session, "assembled_or_rta")
    assert values == ["Assembled", "Unassembled/RTA"]
    assert list_master_attribute_values(session, "assembly_type") == ["Assembled", "Unassembled/RTA"]


def test_import_maps_and_drops_polluted_assembled_or_rta(catalog_intent_session):
    session = catalog_intent_session
    ensure_default_manual_attributes(session)

    result = import_master_sku_dataframe(
        session,
        pd.DataFrame(
            [
                {
                    "sku": "ACH-W0930",
                    "Item": "W0930",
                    "Category": "Kitchen Cabinets : Port & Bell : Anna Caramel Harvest",
                    "Product Category": "Kitchen Cabinets",
                    "Item Style": "Anna Caramel Harvest - Assembled",
                    "Assembled or RTA": "RTA",
                },
                {
                    "sku": "ACH-W0930-A",
                    "Item": "W0930",
                    "Category": "Kitchen Cabinets : Port & Bell : Anna Caramel Harvest",
                    "Product Category": "Kitchen Cabinets",
                    "Item Style": "Anna Caramel Harvest - Assembled",
                    "Assembled or RTA": "Assembled",
                },
                {
                    "sku": "ACH-PKG",
                    "Item": "PKG",
                    "Category": "Kitchen Cabinets : Port & Bell : Anna Caramel Harvest",
                    "Product Category": "Kitchen Cabinets",
                    "Item Style": "Anna Caramel Harvest - Assembled",
                    "Assembled or RTA": "bundle",
                },
            ]
        ),
        source_label="test_manual_attr_vocab",
        reconcile_taxonomy=False,
    )
    assert result["inserted"] == 3

    values = {
        row.sku: row.value
        for row in session.scalars(
            select(MasterProductAttributeValue).where(
                MasterProductAttributeValue.attribute_code == "assembled_or_rta"
            )
        ).all()
    }
    assert values["ACH-W0930"] == "Unassembled/RTA"
    assert values["ACH-W0930-A"] == "Assembled"
    assert "ACH-PKG" not in values

    products = {
        row.sku: row.assembly_type
        for row in session.scalars(select(MasterProduct).where(MasterProduct.sku.in_(list(values) + ["ACH-PKG"]))).all()
    }
    assert products["ACH-W0930"] == "RTA"
    assert products["ACH-W0930-A"] == "Assembled"
    # bundle dropped from attr; assembly_type may still derive from Item Style heuristics
    assert products["ACH-PKG"] in {None, "Assembled"}


def test_default_manual_attributes_contract():
    assert DEFAULT_MANUAL_ATTRIBUTES[0]["attribute_code"] == "assembled_or_rta"
    assert [v["value"] for v in DEFAULT_MANUAL_ATTRIBUTES[0]["values"]] == [
        "Assembled",
        "Unassembled/RTA",
    ]
