"""
Case conversion utilities for API payloads.
"""
import re
from typing import Any, Dict, List


_FIRST_CAP_RE = re.compile(r"(.)([A-Z][a-z]+)")
_ALL_CAP_RE = re.compile(r"([a-z0-9])([A-Z])")

_SPECIAL_ALIASES = {
    "avatar_url": "avatar",
    "avatarUrl": "avatar",
}


def to_snake(name: str) -> str:
    """Convert camelCase/PascalCase to snake_case."""
    if not isinstance(name, str) or not name:
        return name
    if name.lower() == name:
        return name
    s1 = _FIRST_CAP_RE.sub(r"\1_\2", name)
    s2 = _ALL_CAP_RE.sub(r"\1_\2", s1)
    return s2.lower()


def to_camel(name: str) -> str:
    """Convert snake_case to camelCase."""
    if not isinstance(name, str) or not name:
        return name
    if "_" not in name:
        return name
    parts = name.split("_")
    if not parts:
        return name
    first = parts[0]
    rest = "".join(part.capitalize() if part else "_" for part in parts[1:])
    return first + rest


def convert_keys_to_snake(data: Any) -> Any:
    """Recursively convert dict keys to snake_case."""
    if isinstance(data, list):
        return [convert_keys_to_snake(item) for item in data]
    if isinstance(data, dict):
        converted: Dict[Any, Any] = {}
        for key, value in data.items():
            new_key = to_snake(key) if isinstance(key, str) else key
            converted[new_key] = convert_keys_to_snake(value)
        return converted
    return data


def add_camelcase_aliases(data: Any) -> Any:
    """Recursively add camelCase aliases for snake_case keys."""
    if isinstance(data, list):
        return [add_camelcase_aliases(item) for item in data]
    if isinstance(data, dict):
        result: Dict[Any, Any] = {}
        for key, value in data.items():
            result[key] = add_camelcase_aliases(value)
        # Add camelCase aliases without overriding existing keys
        for key, value in list(result.items()):
            if isinstance(key, str):
                camel_key = to_camel(key)
                if camel_key != key and camel_key not in result:
                    result[camel_key] = value
                alias_key = _SPECIAL_ALIASES.get(key)
                if alias_key and alias_key not in result:
                    result[alias_key] = value
        return result
    return data
