from __future__ import annotations
from .string_helpers import camel_to_kebab
from typing import Any, Dict, Optional
import html
from tailwind_merge import TailwindMerge

_twm = TailwindMerge()

# Map Python-safe names to HTML attributes
ALIAS_MAP = {
    "class_name": "class",
    "className": "class",
    "html_for": "for",
    "htmlFor": "for"
}


def merge_classes(*classes: Any) -> str:
    parts: list[str] = []
    for c in classes:
        if not c:
            continue
        if isinstance(c, (list, tuple, set)):
            s = " ".join(str(x) for x in c if x)
        else:
            s = str(c).strip()
        if s:
            parts.append(s)
    return _twm.merge(*parts) if parts else ""


def _to_attr_value(v: Any) -> Optional[str]:
    # XML-strict: booleans should have explicit values
    if v is None:
        return None
    if isinstance(v, bool):
        return "true" if v else None  # omit false
    if isinstance(v, (list, tuple, set)):
        s = " ".join(str(x) for x in v if x)
        return s if s else None
    s = str(v)
    return s if s != "" else None


def get_attributes(props: Dict[str, Any], overrides: Optional[Dict[str, Any]] = None) -> str:
    """
    Build ONE attribute string.
    - Aliases (class_name -> class) are always resolved.
    - If the VALUE contains mustache syntax (e.g. "{var}"), the KEY is converted to kebab-case.
    - Otherwise, the KEY maintains its original casing.
    - Overrides take priority over props.
    """

    final_attrs: Dict[str, str] = {}

    def process_dict(d: Dict[str, Any]):
        if not d:
            return
        for k, v in d.items():
            if not k:
                continue

            # 1. Check Alias Map first (e.g., class_name -> class)
            key_name = ALIAS_MAP.get(k, k)

            # 2. Process value to string
            val = _to_attr_value(v)

            if val is not None:
                # 3. Check for mustache syntax to decide on casing
                # If value is a binding (has { and }), force kebab-case on the key
                if "{" in val and "}" in val:
                    final_key = camel_to_kebab(key_name)
                else:
                    # Otherwise, keep original casing (e.g. standard attributes)
                    final_key = key_name

                final_attrs[final_key] = val

    # 1. Process base props
    process_dict(props)

    # 2. Process overrides (these will overwrite keys from step 1)
    if overrides:
        process_dict(overrides)

    # 3. Build string
    parts: list[str] = []
    # Sorting keys is optional but helpful for consistent testing/output
    for k, v in final_attrs.items():
        parts.append(f'{k}="{html.escape(v, quote=True)}"')

    return " ".join(parts)
