"""Balance widget block aligned with Smartbank Figma design system.

Provides a card balance widget for displaying total balance with
grouped card and account balances.
"""

from __future__ import annotations

from typing import TypedDict

import pydivkit as dk

from smarty_ui.composites.card_balance_item import card_balance_item
from smarty_ui.tokens.theme import Theme, default_theme


class CardBalanceData(TypedDict, total=False):
    """Data structure for a card balance item."""

    balance: str
    card_name: str
    card_thumbnail_url: str | None
    card_last_digits: str | None
    currency: str
    action_url: str | None


class BalanceSectionData(TypedDict, total=False):
    """Data structure for a balance section."""

    title: str
    items: list[CardBalanceData]


def cards_own_list(
    cards: list[CardBalanceData],
    *,
    theme: Theme = default_theme,
    corner_radius: int = 8,
    padding: int = 16,
) -> dk.DivContainer:
    """Cards own list component matching Smartbank Figma design.

    A simple card list widget with no header or footer, just the cards.

    Args:
        cards: List of card balance data
        theme: Theme tokens to use
        corner_radius: Border radius (default 8)
        padding: Container padding (default 16)

    Returns:
        A DivContainer representing the cards list
    """
    content_items: list[dk.Div] = []

    for i, card_data in enumerate(cards):
        item = card_balance_item(
            balance=card_data.get("balance", "0"),
            card_name=card_data.get("card_name", ""),
            card_thumbnail_url=card_data.get("card_thumbnail_url"),
            card_last_digits=card_data.get("card_last_digits"),
            currency=card_data.get("currency", "сум"),
            action_url=card_data.get("action_url"),
            theme=theme,
        )

        # Add top margin for items after the first
        if i > 0:
            item = dk.DivContainer(
                orientation=dk.DivContainerOrientation.VERTICAL,
                width=dk.DivMatchParentSize(),
                margins=dk.DivEdgeInsets(top=12),
                items=[item],
            )

        content_items.append(item)

    # Build card container
    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.VERTICAL,
        width=dk.DivMatchParentSize(),
        border=dk.DivBorder(
            corner_radius=corner_radius,
            stroke=dk.DivStroke(color=theme.colors.grey_light, width=1),
        ),
        background=[dk.DivSolidBackground(color=theme.colors.background)],
        paddings=dk.DivEdgeInsets(
            left=padding,
            right=padding,
            top=padding,
            bottom=padding,
        ),
        items=content_items,
    )


def balance_widget(
    total_balance: str,
    *,
    cards_section: BalanceSectionData | None = None,
    accounts_section: BalanceSectionData | None = None,
    wallet_icon_url: str | None = None,
    currency: str = "сум",
    corner_radius: int = 8,
    padding: int = 16,
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Balance widget component matching Smartbank Figma design.

    A white card container with:
    - Wallet icon in blue-light circle
    - Total balance (Title 02 - Bold 20px)
    - Cards section with header and card items
    - Accounts section with header and account items

    Args:
        total_balance: Formatted total balance string (e.g., "22 941 849 654")
        cards_section: Optional section for cards with title and items
        accounts_section: Optional section for accounts with title and items
        wallet_icon_url: URL to wallet icon image
        currency: Currency suffix (default "сум")
        corner_radius: Border radius (default 8)
        padding: Container padding (default 16)
        theme: Theme tokens to use

    Returns:
        A DivContainer representing the balance widget
    """
    content_items: list[dk.Div] = []

    # Header row: wallet icon + total balance
    header_row = _build_header(
        total_balance=total_balance,
        wallet_icon_url=wallet_icon_url,
        currency=currency,
        theme=theme,
    )
    content_items.append(header_row)

    # Cards section
    if cards_section:
        section = _build_section(
            title=cards_section.get("title", "Баланс ваших карт:"),
            items=cards_section.get("items", []),
            theme=theme,
        )
        content_items.append(section)

    # Accounts section
    if accounts_section:
        section = _build_section(
            title=accounts_section.get("title", "Баланс ваших счетов:"),
            items=accounts_section.get("items", []),
            theme=theme,
        )
        content_items.append(section)

    # Build card container
    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.VERTICAL,
        width=dk.DivMatchParentSize(),
        border=dk.DivBorder(
            corner_radius=corner_radius,
            stroke=dk.DivStroke(color=theme.colors.grey_light, width=1),
        ),
        background=[dk.DivSolidBackground(color=theme.colors.background)],
        paddings=dk.DivEdgeInsets(
            left=padding,
            right=padding,
            top=padding,
            bottom=padding,
        ),
        items=content_items,
    )


def _build_header(
    total_balance: str,
    *,
    wallet_icon_url: str | None = None,
    currency: str = "сум",
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Build the header row with wallet icon and total balance.

    Args:
        total_balance: Formatted total balance string
        wallet_icon_url: URL to wallet icon image
        currency: Currency suffix
        theme: Theme tokens to use

    Returns:
        A DivContainer representing the header row
    """
    header_items: list[dk.Div] = []

    # Wallet icon in blue-light circle
    if wallet_icon_url:
        icon_container = dk.DivContainer(
            orientation=dk.DivContainerOrientation.HORIZONTAL,
            content_alignment_horizontal=dk.DivContentAlignmentHorizontal.CENTER,
            content_alignment_vertical=dk.DivAlignmentVertical.CENTER,
            width=dk.DivFixedSize(value=48),
            height=dk.DivFixedSize(value=48),
            border=dk.DivBorder(corner_radius=24),
            background=[dk.DivSolidBackground(color=theme.colors.blue_light)],
            items=[
                dk.DivImage(
                    image_url=wallet_icon_url,
                    width=dk.DivFixedSize(value=24),
                    height=dk.DivFixedSize(value=24),
                    scale=dk.DivImageScale.FIT,
                )
            ],
        )
        header_items.append(icon_container)

    # Total balance text (Title 02 - Bold 20px)
    title_style = theme.typography.get_title_2()
    total_text = dk.DivText(
        text=f"{total_balance} {currency}",
        font_size=title_style.size,
        font_weight=dk.DivFontWeight(title_style.weight),
        text_color=theme.colors.text_primary,
        line_height=title_style.line_height,
        width=dk.DivMatchParentSize(weight=1),
        margins=dk.DivEdgeInsets(left=16) if wallet_icon_url else None,
    )
    header_items.append(total_text)

    # Header row container
    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.HORIZONTAL,
        content_alignment_vertical=dk.DivAlignmentVertical.CENTER,
        width=dk.DivMatchParentSize(),
        items=header_items,
    )


def _build_list(
    items: list[CardBalanceData],
    *,
    theme: Theme = default_theme,
) -> list[dk.Div]:
    """Build a list of card balance items.

    Args:
        items: List of card balance data
        theme: Theme tokens to use

    Returns:
        A list of DivContainer items
    """
    result: list[dk.Div] = []

    for i, card_data in enumerate(items):
        item = card_balance_item(
            balance=card_data.get("balance", "0"),
            card_name=card_data.get("card_name", ""),
            card_thumbnail_url=card_data.get("card_thumbnail_url"),
            card_last_digits=card_data.get("card_last_digits"),
            currency=card_data.get("currency", "сум"),
            action_url=card_data.get("action_url"),
            theme=theme,
        )

        # Wrap with margin
        item = dk.DivContainer(
            orientation=dk.DivContainerOrientation.VERTICAL,
            width=dk.DivMatchParentSize(),
            margins=dk.DivEdgeInsets(top=12),
            items=[item],
        )
        result.append(item)

    return result


def _build_section(
    title: str,
    items: list[CardBalanceData],
    *,
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Build a balance section with title and card items.

    Args:
        title: Section header text
        items: List of card balance data
        theme: Theme tokens to use

    Returns:
        A DivContainer representing the section
    """
    section_items: list[dk.Div] = []

    # Section header (Controls 02 Bold 14px)
    controls_style = theme.typography.get_controls_2(bold=True)
    header = dk.DivText(
        text=title,
        font_size=controls_style.size,
        font_weight=dk.DivFontWeight(controls_style.weight),
        text_color=theme.colors.text_primary,
        line_height=controls_style.line_height,
        width=dk.DivMatchParentSize(),
    )
    section_items.append(header)

    # Card items
    section_items.extend(_build_list(items, theme=theme))

    return dk.DivContainer(
        orientation=dk.DivContainerOrientation.VERTICAL,
        width=dk.DivMatchParentSize(),
        margins=dk.DivEdgeInsets(top=16),
        items=section_items,
    )


def simple_balance_widget(
    total_balance: str,
    cards: list[CardBalanceData],
    *,
    wallet_icon_url: str | None = None,
    currency: str = "сум",
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Simple balance widget with just cards section.

    Args:
        total_balance: Formatted total balance string
        cards: List of card balance data
        wallet_icon_url: URL to wallet icon image
        currency: Currency suffix
        theme: Theme tokens to use

    Returns:
        A balance widget with cards section only
    """
    return balance_widget(
        total_balance,
        cards_section={"title": "Баланс ваших карт:", "items": cards},
        wallet_icon_url=wallet_icon_url,
        currency=currency,
        theme=theme,
    )


def full_balance_widget(
    total_balance: str,
    cards: list[CardBalanceData],
    accounts: list[CardBalanceData],
    *,
    wallet_icon_url: str | None = None,
    cards_title: str = "Баланс ваших карт:",
    accounts_title: str = "Баланс ваших счетов:",
    currency: str = "сум",
    theme: Theme = default_theme,
) -> dk.DivContainer:
    """Full balance widget with both cards and accounts sections.

    Args:
        total_balance: Formatted total balance string
        cards: List of card balance data
        accounts: List of account balance data
        wallet_icon_url: URL to wallet icon image
        cards_title: Title for cards section
        accounts_title: Title for accounts section
        currency: Currency suffix
        theme: Theme tokens to use

    Returns:
        A balance widget with both sections
    """
    return balance_widget(
        total_balance,
        cards_section={"title": cards_title, "items": cards},
        accounts_section={"title": accounts_title, "items": accounts},
        wallet_icon_url=wallet_icon_url,
        currency=currency,
        theme=theme,
    )
