"""Internal layout helpers: hstack, vstack, and padding utilities.

Provides SwiftUI-like layout helpers for building DivKit UIs:
- HStack: Horizontal stack (row layout)
- VStack: Vertical stack (column layout)
- padded: Add padding around a single element
"""
from __future__ import annotations

from typing import Literal, Sequence

import pydivkit as dk

# Type aliases for alignment
VerticalAlignment = Literal["top", "center", "bottom", "baseline"]
HorizontalAlignment = Literal["left", "center", "right", "start", "end"]


def _apply_gap_with_margins(
    items: Sequence[dk.Div],
    gap: int,
    orientation: Literal["horizontal", "vertical"],
) -> list[dk.Div]:
    """Apply gap between items using margins instead of separators.

    This is more efficient and doesn't add extra elements.
    """
    if not items or gap <= 0:
        return list(items)

    result: list[dk.Div] = []
    for i, item in enumerate(items):
        if i > 0:
            # Apply margin to create gap
            if orientation == "horizontal":
                # Wrap item with left margin
                wrapped = dk.DivContainer(
                    orientation=dk.DivContainerOrientation.HORIZONTAL,
                    width=dk.DivWrapContentSize(),
                    height=dk.DivWrapContentSize(),
                    margins=dk.DivEdgeInsets(left=gap),
                    items=[item],
                )
                result.append(wrapped)
            else:
                # Wrap item with top margin
                wrapped = dk.DivContainer(
                    orientation=dk.DivContainerOrientation.VERTICAL,
                    width=dk.DivWrapContentSize(),
                    height=dk.DivWrapContentSize(),
                    margins=dk.DivEdgeInsets(top=gap),
                    items=[item],
                )
                result.append(wrapped)
        else:
            result.append(item)

    return result


def HStack(
    items: Sequence[dk.Div],
    *,
    gap: int = 0,
    align_v: VerticalAlignment = "center",
    align_h: HorizontalAlignment | None = None,
    padding: int = 0,
    padding_left: int | None = None,
    padding_right: int | None = None,
    padding_top: int | None = None,
    padding_bottom: int | None = None,
    width: dk.DivSize | None = None,
    height: dk.DivSize | None = None,
    background: str | None = None,
    corner_radius: int | None = None,
    action_url: str | None = None,
) -> dk.DivContainer:
    """Create a horizontal stack (row) from a list of items.

    A factory function that creates a horizontal DivContainer with
    flexible configuration options.

    Args:
        items: List of Div elements to stack horizontally
        gap: Space between items in dp (default 0)
        align_v: Vertical alignment - "top", "center", "bottom", "baseline"
        align_h: Horizontal content alignment - "left", "center", "right", "start", "end"
        padding: Uniform padding on all sides
        padding_left: Left padding (overrides `padding`)
        padding_right: Right padding (overrides `padding`)
        padding_top: Top padding (overrides `padding`)
        padding_bottom: Bottom padding (overrides `padding`)
        width: Width sizing (default: wrap content)
        height: Height sizing (default: wrap content)
        background: Optional background color
        corner_radius: Optional border radius
        action_url: Optional tap action URL

    Returns:
        A DivContainer with horizontal orientation

    Example:
        >>> HStack([button1, button2, button3], gap=8, align_v="center")
        >>> HStack([icon, label], gap=4, padding=16)
    """
    # Apply gap between items
    spaced_items = _apply_gap_with_margins(items, gap, "horizontal")

    # Build kwargs
    kwargs: dict = {
        "orientation": dk.DivContainerOrientation.HORIZONTAL,
        "items": spaced_items,
    }

    # Vertical alignment
    align_v_map = {
        "top": dk.DivContentAlignmentVertical.TOP,
        "center": dk.DivContentAlignmentVertical.CENTER,
        "bottom": dk.DivContentAlignmentVertical.BOTTOM,
        "baseline": dk.DivContentAlignmentVertical.BASELINE,
    }
    kwargs["content_alignment_vertical"] = align_v_map.get(
        align_v, dk.DivContentAlignmentVertical.CENTER
    )

    # Horizontal alignment (optional)
    if align_h:
        align_h_map = {
            "left": dk.DivContentAlignmentHorizontal.LEFT,
            "center": dk.DivContentAlignmentHorizontal.CENTER,
            "right": dk.DivContentAlignmentHorizontal.RIGHT,
            "start": dk.DivContentAlignmentHorizontal.START,
            "end": dk.DivContentAlignmentHorizontal.END,
        }
        kwargs["content_alignment_horizontal"] = align_h_map.get(
            align_h, dk.DivContentAlignmentHorizontal.LEFT
        )

    # Padding
    p_left = padding_left if padding_left is not None else padding
    p_right = padding_right if padding_right is not None else padding
    p_top = padding_top if padding_top is not None else padding
    p_bottom = padding_bottom if padding_bottom is not None else padding

    if p_left or p_right or p_top or p_bottom:
        kwargs["paddings"] = dk.DivEdgeInsets(
            left=p_left, right=p_right, top=p_top, bottom=p_bottom
        )

    # Size
    if width:
        kwargs["width"] = width
    if height:
        kwargs["height"] = height

    # Background
    if background:
        kwargs["background"] = [dk.DivSolidBackground(color=background)]

    # Border radius
    if corner_radius:
        kwargs["border"] = dk.DivBorder(corner_radius=corner_radius)

    # Action
    if action_url:
        kwargs["actions"] = [dk.DivAction(log_id="hstack_action", url=action_url)]

    return dk.DivContainer(**kwargs)


def VStack(
    items: Sequence[dk.Div],
    *,
    gap: int = 0,
    align_h: HorizontalAlignment = "left",
    align_v: VerticalAlignment | None = None,
    padding: int = 0,
    padding_left: int | None = None,
    padding_right: int | None = None,
    padding_top: int | None = None,
    padding_bottom: int | None = None,
    width: dk.DivSize | None = None,
    height: dk.DivSize | None = None,
    background: str | None = None,
    corner_radius: int | None = None,
    action_url: str | None = None,
) -> dk.DivContainer:
    """Create a vertical stack (column) from a list of items.

    A factory function that creates a vertical DivContainer with
    flexible configuration options.

    Args:
        items: List of Div elements to stack vertically
        gap: Space between items in dp (default 0)
        align_h: Horizontal alignment - "left", "center", "right", "start", "end"
        align_v: Vertical content alignment - "top", "center", "bottom"
        padding: Uniform padding on all sides
        padding_left: Left padding (overrides `padding`)
        padding_right: Right padding (overrides `padding`)
        padding_top: Top padding (overrides `padding`)
        padding_bottom: Bottom padding (overrides `padding`)
        width: Width sizing (default: wrap content)
        height: Height sizing (default: wrap content)
        background: Optional background color
        corner_radius: Optional border radius
        action_url: Optional tap action URL

    Returns:
        A DivContainer with vertical orientation

    Example:
        >>> VStack([title, subtitle, button], gap=12, align_h="center")
        >>> VStack([header, content, footer], gap=16, padding=20)
    """
    # Apply gap between items
    spaced_items = _apply_gap_with_margins(items, gap, "vertical")

    # Build kwargs
    kwargs: dict = {
        "orientation": dk.DivContainerOrientation.VERTICAL,
        "items": spaced_items,
    }

    # Horizontal alignment
    align_h_map = {
        "left": dk.DivContentAlignmentHorizontal.LEFT,
        "center": dk.DivContentAlignmentHorizontal.CENTER,
        "right": dk.DivContentAlignmentHorizontal.RIGHT,
        "start": dk.DivContentAlignmentHorizontal.START,
        "end": dk.DivContentAlignmentHorizontal.END,
    }
    kwargs["content_alignment_horizontal"] = align_h_map.get(
        align_h, dk.DivContentAlignmentHorizontal.LEFT
    )

    # Vertical alignment (optional)
    if align_v:
        align_v_map = {
            "top": dk.DivContentAlignmentVertical.TOP,
            "center": dk.DivContentAlignmentVertical.CENTER,
            "bottom": dk.DivContentAlignmentVertical.BOTTOM,
            "baseline": dk.DivContentAlignmentVertical.BASELINE,
        }
        kwargs["content_alignment_vertical"] = align_v_map.get(
            align_v, dk.DivContentAlignmentVertical.TOP
        )

    # Padding
    p_left = padding_left if padding_left is not None else padding
    p_right = padding_right if padding_right is not None else padding
    p_top = padding_top if padding_top is not None else padding
    p_bottom = padding_bottom if padding_bottom is not None else padding

    if p_left or p_right or p_top or p_bottom:
        kwargs["paddings"] = dk.DivEdgeInsets(
            left=p_left, right=p_right, top=p_top, bottom=p_bottom
        )

    # Size
    if width:
        kwargs["width"] = width
    if height:
        kwargs["height"] = height

    # Background
    if background:
        kwargs["background"] = [dk.DivSolidBackground(color=background)]

    # Border radius
    if corner_radius:
        kwargs["border"] = dk.DivBorder(corner_radius=corner_radius)

    # Action
    if action_url:
        kwargs["actions"] = [dk.DivAction(log_id="vstack_action", url=action_url)]

    return dk.DivContainer(**kwargs)


# =============================================================================
# Legacy functions (backward compatibility)
# =============================================================================


def hstack(
    *items: dk.Div,
    gap: int = 8,
    align_v: str = "center",
    padding: int = 0,
) -> dk.DivContainer:
    """Horizontal stack with even spacing (like a flex row).

    Legacy function - prefer using HStack() for new code.
    """
    spaced: list[dk.Div] = []
    for i, item in enumerate(items):
        if i > 0 and gap > 0:
            spaced.append(
                dk.DivSeparator(
                    delimiter_style=dk.DivSeparatorDelimiterStyle(
                        color="#00000000",
                    ),
                    margins=dk.DivEdgeInsets(left=gap),
                )
            )
        spaced.append(item)

    kwargs: dict = {
        "orientation": dk.DivContainerOrientation.HORIZONTAL,
        "content_alignment_vertical": dk.DivContentAlignmentVertical(align_v.lower()),
        "items": spaced,
    }
    if padding > 0:
        kwargs["paddings"] = dk.DivEdgeInsets(
            left=padding, right=padding, top=padding, bottom=padding,
        )
    return dk.DivContainer(**kwargs)


def vstack(
    *items: dk.Div,
    gap: int = 8,
    align_h: str = "left",
    padding: int = 0,
) -> dk.DivContainer:
    """Vertical stack with even spacing (like a flex column).

    Legacy function - prefer using VStack() for new code.
    """
    spaced: list[dk.Div] = []
    for i, item in enumerate(items):
        if i > 0 and gap > 0:
            spaced.append(
                dk.DivSeparator(
                    delimiter_style=dk.DivSeparatorDelimiterStyle(
                        color="#00000000",
                    ),
                    margins=dk.DivEdgeInsets(top=gap),
                )
            )
        spaced.append(item)

    kwargs: dict = {
        "orientation": dk.DivContainerOrientation.VERTICAL,
        "content_alignment_horizontal": dk.DivContentAlignmentHorizontal(
            align_h.lower(),
        ),
        "items": spaced,
    }
    if padding > 0:
        kwargs["paddings"] = dk.DivEdgeInsets(
            left=padding, right=padding, top=padding, bottom=padding,
        )
    return dk.DivContainer(**kwargs)


def padded(
    child: dk.Div,
    *,
    all: int | None = None,
    left: int = 0,
    right: int = 0,
    top: int = 0,
    bottom: int = 0,
) -> dk.DivContainer:
    """Wrap a single child in a container with padding."""
    if all is not None:
        left = right = top = bottom = all
    return dk.DivContainer(
        items=[child],
        paddings=dk.DivEdgeInsets(
            left=left, right=right, top=top, bottom=bottom,
        ),
    )
