"""Button primitives aligned with Smartbank Figma design system.

Button variants:
- primary_button: Blue background, white text (default CTA)
- secondary_button: Blue-light background, blue text
- outline_button: Border only, blue text
- disabled_button: Grey background, grey text (locked state)

Each button supports two sizes:
- "large": 14px radius, 18px vertical padding, 16px text
- "small": 8px radius, 10px vertical padding, 14px text
"""

from __future__ import annotations

from typing import Literal

import pydivkit as dk

from smarty_ui.tokens.theme import Theme, default_theme

ButtonSize = Literal["large", "small"]


def _make_action(action_url: str | None, log_id: str) -> list[dk.DivAction] | None:
    """Build an action list if a URL is provided."""
    if action_url is None:
        return None
    return [dk.DivAction(log_id=log_id, url=action_url)]


def _get_button_dimensions(size: ButtonSize, theme: Theme) -> tuple[int, int, int, str]:
    """Get corner_radius, padding_v, font_size, font_weight for button size."""
    if size == "large":
        return (
            theme.spacing.radius_md,  # 14px
            theme.spacing.button_padding_v_large,  # 18px
            theme.typography.controls_1_size,  # 16px
            theme.typography.bold_weight,
        )
    else:  # small
        return (
            theme.spacing.radius_sm,  # 8px
            theme.spacing.button_padding_v_small,  # 10px
            theme.typography.controls_2_size,  # 14px
            theme.typography.semibold_weight,
        )


def primary_button(
    text: str,
    *,
    action_url: str | None = None,
    size: ButtonSize = "large",
    width: int | None = None,
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Primary button with blue background and white text.

    The main call-to-action button style.

    Args:
        text: Button label text
        action_url: Optional URL to navigate to on click
        size: "large" (default) or "small"
        width: Optional fixed width in dp, defaults to match parent
        theme: Theme tokens to use
    """
    corner_radius, padding_v, font_size, font_weight = _get_button_dimensions(
        size, theme
    )

    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.HORIZONTAL,
        content_alignment_horizontal=dk.DivContentAlignmentHorizontal.CENTER,
        content_alignment_vertical=dk.DivAlignmentVertical.CENTER,
        width=dk.DivFixedSize(value=width) if width else dk.DivMatchParentSize(),
        height=dk.DivWrapContentSize(),
        border=dk.DivBorder(corner_radius=corner_radius),
        paddings=dk.DivEdgeInsets(
            left=theme.spacing.button_padding_h,
            right=theme.spacing.button_padding_h,
            top=padding_v,
            bottom=padding_v,
        ),
        background=[dk.DivSolidBackground(color=theme.colors.primary)],
        actions=_make_action(action_url, f"btn_primary_{text}"),
        items=[
            dk.DivText(
                text=text,
                font_size=font_size,
                font_weight=dk.DivFontWeight(font_weight),
                text_color=theme.colors.text_on_primary,
                width=dk.DivWrapContentSize(),
                text_alignment_horizontal=dk.DivAlignmentHorizontal.CENTER,
            ),
        ],
    )


def secondary_button(
    text: str,
    *,
    action_url: str | None = None,
    size: ButtonSize = "large",
    width: int | None = None,
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Secondary button with blue-light background and blue text.

    Used for secondary actions that complement the primary button.

    Args:
        text: Button label text
        action_url: Optional URL to navigate to on click
        size: "large" (default) or "small"
        width: Optional fixed width in dp, defaults to match parent
        theme: Theme tokens to use
    """
    corner_radius, padding_v, font_size, font_weight = _get_button_dimensions(
        size, theme
    )

    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.HORIZONTAL,
        content_alignment_horizontal=dk.DivContentAlignmentHorizontal.CENTER,
        content_alignment_vertical=dk.DivAlignmentVertical.CENTER,
        width=dk.DivFixedSize(value=width) if width else dk.DivMatchParentSize(),
        height=dk.DivWrapContentSize(),
        border=dk.DivBorder(corner_radius=corner_radius),
        paddings=dk.DivEdgeInsets(
            left=theme.spacing.button_padding_h,
            right=theme.spacing.button_padding_h,
            top=padding_v,
            bottom=padding_v,
        ),
        background=[dk.DivSolidBackground(color=theme.colors.blue_light)],
        actions=_make_action(action_url, f"btn_secondary_{text}"),
        items=[
            dk.DivText(
                text=text,
                font_size=font_size,
                font_weight=dk.DivFontWeight(font_weight),
                text_color=theme.colors.primary,
                width=dk.DivWrapContentSize(),
                text_alignment_horizontal=dk.DivAlignmentHorizontal.CENTER,
            ),
        ],
    )


def outline_button(
    text: str,
    *,
    action_url: str | None = None,
    size: ButtonSize = "large",
    width: int | None = None,
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Outline button with border only and blue text.

    Used for tertiary actions or when a lighter visual weight is needed.

    Args:
        text: Button label text
        action_url: Optional URL to navigate to on click
        size: "large" (default) or "small"
        width: Optional fixed width in dp, defaults to match parent
        theme: Theme tokens to use
    """
    corner_radius, padding_v, font_size, font_weight = _get_button_dimensions(
        size, theme
    )

    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.HORIZONTAL,
        content_alignment_horizontal=dk.DivContentAlignmentHorizontal.CENTER,
        content_alignment_vertical=dk.DivAlignmentVertical.CENTER,
        width=dk.DivFixedSize(value=width) if width else dk.DivMatchParentSize(),
        height=dk.DivWrapContentSize(),
        border=dk.DivBorder(
            corner_radius=corner_radius,
            stroke=dk.DivStroke(color=theme.colors.border, width=1),
        ),
        paddings=dk.DivEdgeInsets(
            left=theme.spacing.button_padding_h,
            right=theme.spacing.button_padding_h,
            top=padding_v,
            bottom=padding_v,
        ),
        background=[dk.DivSolidBackground(color=theme.colors.background)],
        actions=_make_action(action_url, f"btn_outline_{text}"),
        items=[
            dk.DivText(
                text=text,
                font_size=font_size,
                font_weight=dk.DivFontWeight(font_weight),
                text_color=theme.colors.primary,
                width=dk.DivWrapContentSize(),
                text_alignment_horizontal=dk.DivAlignmentHorizontal.CENTER,
            ),
        ],
    )


def disabled_button(
    text: str,
    *,
    size: ButtonSize = "large",
    width: int | None = None,
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Disabled/locked button with grey background and grey text.

    Used to indicate an action is not currently available.
    Note: No action_url parameter as disabled buttons shouldn't be interactive.

    Args:
        text: Button label text
        size: "large" (default) or "small"
        width: Optional fixed width in dp, defaults to match parent
        theme: Theme tokens to use
    """
    corner_radius, padding_v, font_size, font_weight = _get_button_dimensions(
        size, theme
    )

    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.HORIZONTAL,
        content_alignment_horizontal=dk.DivContentAlignmentHorizontal.CENTER,
        content_alignment_vertical=dk.DivAlignmentVertical.CENTER,
        width=dk.DivFixedSize(value=width) if width else dk.DivMatchParentSize(),
        height=dk.DivWrapContentSize(),
        border=dk.DivBorder(corner_radius=corner_radius),
        paddings=dk.DivEdgeInsets(
            left=theme.spacing.button_padding_h,
            right=theme.spacing.button_padding_h,
            top=padding_v,
            bottom=padding_v,
        ),
        background=[dk.DivSolidBackground(color=theme.colors.disabled_bg)],
        items=[
            dk.DivText(
                text=text,
                font_size=font_size,
                font_weight=dk.DivFontWeight(font_weight),
                text_color=theme.colors.disabled_text,
                width=dk.DivWrapContentSize(),
                text_alignment_horizontal=dk.DivAlignmentHorizontal.CENTER,
            ),
        ],
    )


def icon_button(
    icon_url: str,
    *,
    action_url: str | None = None,
    size: int = 44,
    icon_size: int = 24,
    corner_radius: int | None = None,
    tint_color: str | None = None,
    bg_color: str | None = None,
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Circular icon-only button.

    Args:
        icon_url: URL to the icon image
        action_url: Optional URL to navigate to on click
        size: Button size in dp (default 44)
        icon_size: Icon size in dp (default 24)
        corner_radius: Border radius, defaults to size/2 for circle
        tint_color: Optional tint color for the icon
        bg_color: Background color, defaults to surface color
        theme: Theme tokens to use
    """
    radius = corner_radius if corner_radius is not None else size // 2
    img_kwargs: dict = {
        "image_url": icon_url,
        "width": dk.DivFixedSize(value=icon_size),
        "height": dk.DivFixedSize(value=icon_size),
    }
    if tint_color:
        img_kwargs["tint_color"] = tint_color

    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.HORIZONTAL,
        content_alignment_horizontal=dk.DivContentAlignmentHorizontal.CENTER,
        content_alignment_vertical=dk.DivAlignmentVertical.CENTER,
        width=dk.DivFixedSize(value=size),
        height=dk.DivFixedSize(value=size),
        border=dk.DivBorder(corner_radius=radius),
        background=[dk.DivSolidBackground(color=bg_color or theme.colors.surface)],
        actions=_make_action(action_url, "icon_btn"),
        items=[dk.DivImage(**img_kwargs)],
    )


def text_button(
    text: str,
    *,
    action_url: str | None = None,
    color: str | None = None,
    size: ButtonSize = "large",
    theme: Theme = default_theme,
) -> dk.DivText:
    """Minimal text-only button (looks like a link).

    Args:
        text: Button label text
        action_url: Optional URL to navigate to on click
        color: Text color, defaults to primary
        size: "large" or "small" affects font size
        theme: Theme tokens to use
    """
    _, _, font_size, font_weight = _get_button_dimensions(size, theme)

    return dk.DivText(
        text=text,
        font_size=font_size,
        font_weight=dk.DivFontWeight(font_weight),
        text_color=color or theme.colors.primary,
        width=dk.DivWrapContentSize(),
        actions=_make_action(action_url, f"txt_btn_{text}"),
    )
