from __future__ import annotations

from copy import deepcopy
from typing import Any

BUTTON_BACKGROUND_COLORS: tuple[str, ...] = (
    "transparent",
    "#FB9337",
    "#FA6F32",
    "#FAB300",
    "#67C200",
    "#00BD77",
    "#00C5FB",
    "#268BFB",
    "#001A72",
    "#9E64FB",
    "#D164FB",
    "#FB4B51",
    "#FFFFFF",
)

BUTTON_TEXT_COLORS: tuple[str, ...] = (
    "#FB9337",
    "#FA6F32",
    "#FAB300",
    "#67C200",
    "#00BD77",
    "#00C5FB",
    "#268BFB",
    "#001A72",
    "#9E64FB",
    "#D164FB",
    "#FB4B51",
    "#494F57",
    "#FFFFFF",
)

BUTTON_ICONS: tuple[str, ...] = (
    "ex-print",
    "ex-attachment",
    "ex-handoff",
    "ex-delete",
    "ex-copy",
    "ex-share",
    "ex-edit2",
    "ex-admin-outlined",
    "ex-stamp",
    "ex-kanban",
    "ex-update",
    "ex-tickincircle-outlined",
    "ex-crossincircle-outlined",
    "ex-plus-circle",
    "ex-logout",
    "ex-check",
    "ex-rename",
    "ex-locked",
    "ex-shift",
    "ex-new-tabpage",
    "ex-cross",
    "ex-switch",
    "ex-layer",
    "ex-import",
    "ex-pin-outlined",
    "ex-disabled",
    "ex-duplicate",
    "ex-heart-outlined",
    "ex-plus",
    "ex-save",
    "ex-upload",
    "ex-upgrade1",
    "ex-downgrade",
    "ex-unfold",
    "ex-fold",
    "ex-sort",
    "ex-menu-control",
    "ex-download",
    "ex-insert-below",
    "ex-left-outlined-double",
    "ex-right-outlined-double",
    "ex-recovery",
    "ex-layout",
    "ex-search",
    "ex-preview",
    "ex-invisible",
    "ex-carboncopy",
    "ex-basicInfo",
    "ex-fillIn",
    "ex-refresh",
    "ex-display",
    "ex-message",
    "ex-edit",
    "ex-heart-filled",
    "ex-pin-filled",
    "ex-transfer",
    "ex-cross-circle",
    "ex-clock",
    "ex-admin-filled",
    "ex-tickincircle-circle",
    "ex-all-application",
    "ex-help-filled",
    "ex-streamline",
    "ex-table",
    "ex-rowheight-short",
    "ex-rowheight-medium",
    "ex-rowheight-tall",
    "ex-rowheight-tallest",
)

BUTTON_STYLE_PRESETS: tuple[dict[str, Any], ...] = (
    {
        "key": "primary_blue",
        "label": "Primary Blue",
        "button_type": "default",
        "background_color": "#268BFB",
        "text_color": "#FFFFFF",
        "recommended_icons": ["ex-plus-circle", "ex-plus"],
    },
    {
        "key": "text_blue",
        "label": "Text Blue",
        "button_type": "text",
        "background_color": "transparent",
        "text_color": "#268BFB",
        "recommended_icons": ["ex-share", "ex-new-tabpage"],
    },
    {
        "key": "warning_orange",
        "label": "Warning Orange",
        "button_type": "default",
        "background_color": "#FB9337",
        "text_color": "#FFFFFF",
        "recommended_icons": ["ex-message", "ex-clock"],
    },
    {
        "key": "danger_red",
        "label": "Danger Red",
        "button_type": "default",
        "background_color": "#FB4B51",
        "text_color": "#FFFFFF",
        "recommended_icons": ["ex-delete", "ex-cross-circle"],
    },
    {
        "key": "neutral_outline",
        "label": "Neutral Outline",
        "button_type": "default",
        "background_color": "#FFFFFF",
        "text_color": "#494F57",
        "recommended_icons": ["ex-edit", "ex-search"],
    },
    {
        "key": "secondary_gray",
        "label": "Secondary Gray",
        "button_type": "text",
        "background_color": "transparent",
        "text_color": "#494F57",
        "recommended_icons": ["ex-edit", "ex-search"],
    },
)

_PRESET_BY_KEY: dict[str, dict[str, Any]] = {
    str(item["key"]).strip(): dict(item) for item in BUTTON_STYLE_PRESETS
}

_COLOR_FAMILY_BY_VALUE: dict[str, str] = {
    "transparent": "neutral",
    "#FB9337": "orange",
    "#FA6F32": "orange",
    "#FAB300": "yellow",
    "#67C200": "green",
    "#00BD77": "green",
    "#00C5FB": "cyan",
    "#268BFB": "blue",
    "#001A72": "blue",
    "#9E64FB": "purple",
    "#D164FB": "purple",
    "#FB4B51": "red",
    "#FFFFFF": "white",
    "#494F57": "gray",
}


def _normalize_color_value(value: str | None) -> str | None:
    normalized = str(value or "").strip()
    if not normalized:
        return None
    lowered = normalized.lower().replace(" ", "")
    if lowered == "transparent":
        return "transparent"
    if lowered in {
        "#fff",
        "#ffffff",
        "white",
        "rgb(255,255,255)",
        "rgba(255,255,255,1)",
    }:
        return "#FFFFFF"
    if normalized.startswith("#"):
        return normalized.upper()
    return normalized


def button_style_catalog_payload() -> dict[str, Any]:
    return {
        "icons": [{"value": icon, "label": icon} for icon in BUTTON_ICONS],
        "background_colors": [
            {
                "value": color,
                "label": color,
                "family": _COLOR_FAMILY_BY_VALUE.get(color, "custom"),
            }
            for color in BUTTON_BACKGROUND_COLORS
        ],
        "text_colors": [
            {
                "value": color,
                "label": color,
                "family": _COLOR_FAMILY_BY_VALUE.get(color, "custom"),
            }
            for color in BUTTON_TEXT_COLORS
        ],
        "presets": [deepcopy(item) for item in BUTTON_STYLE_PRESETS],
    }


def resolve_button_style(
    *,
    style_preset: str | None,
    button_icon: str | None,
    background_color: str | None,
    text_color: str | None,
    require_complete_style: bool,
) -> dict[str, str | None]:
    preset_key = str(style_preset or "").strip() or None
    resolved_icon = str(button_icon or "").strip() or None
    resolved_background = _normalize_color_value(background_color)
    resolved_text = _normalize_color_value(text_color)

    if preset_key is not None:
        preset = _PRESET_BY_KEY.get(preset_key)
        if preset is None:
            raise ValueError(
                "unsupported style_preset; use button_style_catalog_get to inspect available presets"
            )
        if resolved_background is None:
            resolved_background = str(preset["background_color"])
        if resolved_text is None:
            resolved_text = str(preset["text_color"])
        if resolved_icon is None:
            recommended = preset.get("recommended_icons") or []
            if recommended:
                resolved_icon = str(recommended[0]).strip() or None

    if require_complete_style:
        missing: list[str] = []
        if resolved_icon is None:
            missing.append("button_icon")
        if resolved_background is None:
            missing.append("background_color")
        if resolved_text is None:
            missing.append("text_color")
        if missing:
            raise ValueError(f"button style requires {', '.join(missing)}")

    if resolved_icon is not None and resolved_icon not in BUTTON_ICONS:
        raise ValueError(
            "unsupported button_icon; use button_style_catalog_get to inspect available icons"
        )
    if resolved_background is not None and resolved_background not in BUTTON_BACKGROUND_COLORS:
        raise ValueError(
            "unsupported background_color; current frontend only supports template colors from button_style_catalog_get"
        )
    if resolved_text is not None and resolved_text not in BUTTON_TEXT_COLORS:
        raise ValueError(
            "unsupported text_color; current frontend only supports template colors from button_style_catalog_get"
        )

    return {
        "style_preset": preset_key,
        "button_icon": resolved_icon,
        "background_color": resolved_background,
        "text_color": resolved_text,
    }
