"""Pure helpers for matching feed category paths to Magento registry rows.

Feed/master data often uses slug paths (``kitchen-cabinets/wall-cabinets``) while
``magento_category_registry.path_names`` stores Magento display names
(``Default Category/Kitchen Cabinets/Wall Cabinets``). Exact string equality fails;
normalize both sides before matching.
"""

from __future__ import annotations

import re
from typing import Any, Dict, Iterable, List, Optional, Set

from channel.url_canonical import normalize_plp_path, slugify_segment

MAGENTO_ROOT_PREFIXES = frozenset({"default category", "root catalog"})


def humanize_slug_segment(segment: str) -> str:
    """``kitchen-cabinets`` → ``Kitchen Cabinets``; leave already-human names alone."""
    text = str(segment or "").strip()
    if not text:
        return ""
    if "-" in text and text.lower() == text:
        return text.replace("-", " ").title()
    return text


def humanize_slug_path(path: str) -> str:
    parts = [humanize_slug_segment(p) for p in str(path or "").split("/") if str(p).strip()]
    return "/".join(p for p in parts if p)


def strip_magento_roots(path_names: str) -> str:
    parts = [p.strip() for p in str(path_names or "").split("/") if p.strip()]
    while parts and parts[0].lower() in MAGENTO_ROOT_PREFIXES:
        parts.pop(0)
    return "/".join(parts)


def normalize_category_path(value: str) -> str:
    return re.sub(r"\s+", " ", str(value or "").strip().lower())


def category_path_match_key(value: str) -> str:
    """Collapse slug/human variants: ``kitchen-cabinets`` == ``Kitchen Cabinets``."""
    return re.sub(r"[^a-z0-9]+", "", str(value or "").lower())


def path_candidate_keys(path: str) -> Set[str]:
    raw = str(path or "").strip().strip("/")
    if not raw:
        return set()
    human = humanize_slug_path(raw)
    slug = normalize_plp_path(raw)
    variants = [
        raw,
        human,
        slug,
        strip_magento_roots(raw),
        strip_magento_roots(human),
        f"Default Category/{human}",
        f"Root Catalog/{human}",
        f"Default Category/{slug}",
    ]
    return {category_path_match_key(v) for v in variants if str(v).strip()}


def match_category_id(registry_rows: Iterable[Dict[str, Any]], path: str) -> Optional[int]:
    """Return Magento category_id for a feed path, or None if ambiguous/missing."""
    keys = path_candidate_keys(path)
    if not keys:
        return None

    path_matches: List[Dict[str, Any]] = []
    for row in registry_rows:
        path_names = str(row.get("path_names") or "")
        stripped = strip_magento_roots(path_names)
        row_keys = {
            category_path_match_key(path_names),
            category_path_match_key(stripped),
            category_path_match_key(normalize_plp_path(stripped)),
        }
        if keys & row_keys:
            path_matches.append(row)

    if path_matches:
        path_matches.sort(key=lambda r: len(strip_magento_roots(str(r.get("path_names") or ""))))
        cat_id = path_matches[0].get("category_id") or path_matches[0].get("magento_category_id")
        try:
            return int(cat_id) if cat_id is not None else None
        except (TypeError, ValueError):
            return None

    leaf = str(path).strip().strip("/").split("/")[-1]
    leaf_key = category_path_match_key(leaf)
    if not leaf_key:
        return None
    leaf_matches: List[Dict[str, Any]] = []
    for row in registry_rows:
        name_key = category_path_match_key(str(row.get("name") or ""))
        path_names = str(row.get("path_names") or "")
        leaf_name_key = category_path_match_key(path_names.split("/")[-1] if path_names else "")
        if leaf_key in {name_key, leaf_name_key}:
            leaf_matches.append(row)
    if len(leaf_matches) != 1:
        return None
    cat_id = leaf_matches[0].get("category_id") or leaf_matches[0].get("magento_category_id")
    try:
        return int(cat_id) if cat_id is not None else None
    except (TypeError, ValueError):
        return None


def segment_url_key(segment: str) -> str:
    """URL key Magento would typically derive for a category segment."""
    return slugify_segment(humanize_slug_segment(segment) or segment)
