"""Ensure Magento shopping-facet attributes (cabinet_type) exist, are filterable, and option-complete."""

from __future__ import annotations

import logging
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional

from sqlalchemy.orm import Session

from db.shopping_facet_catalog import KITCHEN_CABINET_SHOPPING_OPTIONS, compact_filter_value, magento_option_label
from channel.attribute_value_resolver import norm_option_label

logger = logging.getLogger(__name__)

CABINET_TYPE_ATTRIBUTE = "cabinet_type"


def ensure_magento_shopping_facets(
    session: Session,
    api: Any,
    *,
    connection_id: int,
    dry_run: bool = False,
    attributes: Optional[List[str]] = None,
) -> Dict[str, Any]:
    """Create missing cabinet_type options, verify filterable flag, refresh option registry."""
    from db.magento_repositories import SqlAlchemyAttributeRegistryRepository

    wanted = [str(code).strip() for code in (attributes or [CABINET_TYPE_ATTRIBUTE]) if str(code).strip()]
    result: Dict[str, Any] = {
        "connection_id": connection_id,
        "dry_run": dry_run,
        "attributes": {},
    }
    if CABINET_TYPE_ATTRIBUTE not in wanted:
        return result

    attr_repo = SqlAlchemyAttributeRegistryRepository(session)
    now = datetime.now(timezone.utc)
    cabinet_result: Dict[str, Any] = {
        "attribute_code": CABINET_TYPE_ATTRIBUTE,
        "created_options": [],
        "existing_options": [],
        "filterable_updated": False,
        "errors": [],
        "url_slugs": {},
    }

    status, body = api.get_attribute(CABINET_TYPE_ATTRIBUTE)
    if status != 200 or not body:
        cabinet_result["errors"].append(f"Attribute {CABINET_TYPE_ATTRIBUTE} not found in Magento (HTTP {status})")
        result["attributes"][CABINET_TYPE_ATTRIBUTE] = cabinet_result
        return result

    attribute_id = body.get("attribute_id")
    if attribute_id and attr_repo:
        attr_repo.upsert_attribute(
            connection_id,
            CABINET_TYPE_ATTRIBUTE,
            int(attribute_id),
            frontend_label=str(body.get("default_frontend_label") or "Cabinet Type"),
            frontend_input=str(body.get("frontend_input") or "select"),
            fetched_at=now,
        )

    if not dry_run and not bool(body.get("is_filterable")):
        try:
            update_status, update_body = api.update_attribute(
                CABINET_TYPE_ATTRIBUTE,
                {"is_filterable": 1, "is_filterable_in_search": 1, "is_searchable": 1},
            )
            if update_status in (200, 201):
                cabinet_result["filterable_updated"] = True
            else:
                cabinet_result["errors"].append(
                    f"Failed to set is_filterable on {CABINET_TYPE_ATTRIBUTE}: HTTP {update_status} {update_body}"
                )
        except Exception as exc:
            cabinet_result["errors"].append(f"Failed to set is_filterable: {exc}")

    opt_status, remote_options = api.get_attribute_options(CABINET_TYPE_ATTRIBUTE)
    by_label = {
        norm_option_label(str(item.get("label") or "")): item
        for item in (remote_options or [])
        if isinstance(item, dict)
    }

    for item in KITCHEN_CABINET_SHOPPING_OPTIONS:
        magento_label = str(item["magento_label"])
        slug = compact_filter_value(item["label"])
        cabinet_result["url_slugs"][slug] = magento_label
        norm = norm_option_label(magento_label)
        if norm in by_label:
            cabinet_result["existing_options"].append(magento_label)
            continue
        if dry_run:
            cabinet_result["created_options"].append(magento_label)
            continue
        try:
            create_status, create_body, create_err = api.create_attribute_option(
                CABINET_TYPE_ATTRIBUTE,
                magento_label,
            )
            if create_status in (200, 201):
                cabinet_result["created_options"].append(magento_label)
                by_label[norm] = create_body or {"label": magento_label}
            else:
                cabinet_result["errors"].append(
                    f"Create option '{magento_label}': HTTP {create_status} {create_err or create_body}"
                )
        except Exception as exc:
            cabinet_result["errors"].append(f"Create option '{magento_label}': {exc}")

    if not dry_run and attr_repo:
        refresh_status, refreshed = api.get_attribute_options(CABINET_TYPE_ATTRIBUTE)
        if refresh_status == 200 and refreshed:
            rows = []
            slug_by_index: Dict[str, str] = {}
            for option in refreshed:
                if not isinstance(option, dict):
                    continue
                label = str(option.get("label") or "").strip()
                value_index = option.get("value") or option.get("value_index")
                if not label or value_index is None:
                    continue
                try:
                    index = int(value_index)
                except (ValueError, TypeError):
                    continue
                rows.append({"label": label, "value_index": index})
                slug = compact_filter_value(label)
                slug_by_index[str(index)] = slug
            if rows:
                attr_repo.bulk_upsert_options(connection_id, CABINET_TYPE_ATTRIBUTE, rows, now)
            cabinet_result["option_registry_count"] = len(rows)
            cabinet_result["url_slugs_by_value_index"] = {
                str(row["value_index"]): compact_filter_value(str(row["label"]))
                for row in rows
            }

    result["attributes"][CABINET_TYPE_ATTRIBUTE] = cabinet_result
    return result


def normalize_row_cabinet_type(row: Dict[str, Any]) -> Dict[str, Any]:
    """Normalize cabinet_type on a snapshot/export row to Magento option labels."""
    out = dict(row)
    raw = str(out.get("cabinet_type") or out.get("cabinet_type_sub_category_1") or "").strip()
    if raw:
        out["cabinet_type"] = magento_option_label(raw)
    return out
