from pathlib import Path
from uuid import uuid4

from sqlalchemy import select

from app.jobs.import_prefix_colors import _load_prefix_color_rows, import_prefix_colors_rows
from db.models import ManualAttributeVocabulary, ManualAttributeVocabularyValue, MasterProduct, MasterProductAttributeValue


def _write_csv(rows: list[tuple[str, str]]) -> str:
    path = Path(__file__).resolve().parent / f"tmp-prefix-colors-{uuid4().hex}.csv"
    lines = ["SKU Prefix,Color"]
    lines.extend(f"{prefix},{color}" for prefix, color in rows)
    path.write_text("\n".join(lines) + "\n", encoding="utf-8")
    return str(path)


def test_import_prefix_colors_dry_run_reports_updates_without_writing(catalog_intent_session):
    session = catalog_intent_session
    session.add_all(
        [
            MasterProduct(
                sku="ACH-B12",
                name="ACH-B12",
                category_l1="Kitchen Cabinets",
                collection="Anna Caramel Harvest",
                row_hash="h-ach",
                is_active=True,
                raw_payload={},
            ),
            MasterProduct(
                sku="RTA-ACH-B12",
                name="RTA-ACH-B12",
                category_l1="Kitchen Cabinets",
                collection="Anna Caramel Harvest",
                row_hash="h-rta-ach",
                is_active=True,
                raw_payload={},
            ),
        ]
    )
    session.flush()

    csv_path = _write_csv(
        [
            ("ACH-", "Wood Tone"),
            ("RTA-ACH-", "Brown"),
        ],
    )

    try:
        prefix_rows = _load_prefix_color_rows(csv_path)
        result = import_prefix_colors_rows(
            session,
            prefix_rows,
            dry_run=True,
            source_label="test_prefix_colors",
        )
        session.rollback()
    finally:
        Path(csv_path).unlink(missing_ok=True)

    assert result["status"] == "ok"
    assert result["would_update_products"] == 2
    assert result["updated_products"] == 0
    assert session.scalar(select(ManualAttributeVocabulary).limit(1)) is None
    assert session.scalar(select(MasterProductAttributeValue).limit(1)) is None


def test_import_prefix_colors_apply_updates_products_and_locks_vocabulary(catalog_intent_session):
    session = catalog_intent_session
    session.add_all(
        [
            MasterProduct(
                sku="ACH-B12",
                name="ACH-B12",
                category_l1="Kitchen Cabinets",
                collection="Anna Caramel Harvest",
                row_hash="h-ach",
                is_active=True,
                raw_payload={},
            ),
            MasterProduct(
                sku="RTA-ACH-B12",
                name="RTA-ACH-B12",
                category_l1="Kitchen Cabinets",
                collection="Anna Caramel Harvest",
                row_hash="h-rta-ach",
                is_active=True,
                raw_payload={},
            ),
            MasterProduct(
                sku="ASG-B12",
                name="ASG-B12",
                category_l1="Kitchen Cabinets",
                collection="Anna Stone Gray",
                row_hash="h-asg",
                is_active=True,
                raw_payload={"color": "Legacy"},
            ),
        ]
    )
    session.flush()

    csv_path = _write_csv(
        [
            ("ACH-", "Wood Tone"),
            ("RTA-ACH-", "Brown"),
            ("ASG-", "Gray"),
        ],
    )

    try:
        prefix_rows = _load_prefix_color_rows(csv_path)
        result = import_prefix_colors_rows(
            session,
            prefix_rows,
            dry_run=False,
            source_label="test_prefix_colors",
        )
        session.commit()
    finally:
        Path(csv_path).unlink(missing_ok=True)

    assert result["status"] == "ok"
    assert result["updated_products"] == 3

    ach = session.scalar(select(MasterProduct).where(MasterProduct.sku == "ACH-B12"))
    rta_ach = session.scalar(select(MasterProduct).where(MasterProduct.sku == "RTA-ACH-B12"))
    asg = session.scalar(select(MasterProduct).where(MasterProduct.sku == "ASG-B12"))

    assert ach is not None and ach.raw_payload["color"] == "Wood Tone"
    assert rta_ach is not None and rta_ach.raw_payload["color"] == "Brown"
    assert asg is not None and asg.raw_payload["color"] == "Gray"

    attr_rows = session.scalars(
        select(MasterProductAttributeValue).where(MasterProductAttributeValue.attribute_code == "color")
    ).all()
    assert {row.sku: row.value for row in attr_rows} == {
        "ACH-B12": "Wood Tone",
        "RTA-ACH-B12": "Brown",
        "ASG-B12": "Gray",
    }

    vocab = session.scalar(
        select(ManualAttributeVocabulary).where(ManualAttributeVocabulary.attribute_code == "color")
    )
    assert vocab is not None
    assert vocab.is_locked is True
    assert vocab.unknown_policy == "drop"

    vocab_values = session.scalars(
        select(ManualAttributeVocabularyValue)
        .where(ManualAttributeVocabularyValue.vocabulary_id == vocab.id)
        .order_by(ManualAttributeVocabularyValue.sort_order)
    ).all()
    assert [row.value for row in vocab_values] == ["Brown", "Gray", "Wood Tone"]
