"""Generative UI message components (Card, Accordion) that persist as message content."""

from typing import List, Optional


class CardSection:
    """A key-value section within a Card."""

    def __init__(self, *, label: str, value: str):
        self.label = label
        self.value = value

    def to_dict(self) -> dict:
        return {"label": self.label, "value": self.value}


class CardButton:
    """A button within a Card that links to an external URL.

    Args:
        label: Button text.
        url: URL the button opens.
    """

    def __init__(self, *, label: str, url: str):
        self.label = label
        self.url = url

    def to_dict(self) -> dict:
        return {"label": self.label, "url": self.url}


class Card:
    """A card component for displaying structured information.

    Args:
        title: Card heading.
        body: Optional body text / description.
        variant: Visual style — "default", "success", "warning", "error", or "info".
        sections: Optional list of CardSection key-value pairs.
        image: Optional image URL displayed at the top of the card.
        button: Optional CardButton rendered at the bottom of the card.
    """

    VARIANTS = ("default", "success", "warning", "error", "info")

    def __init__(
        self,
        *,
        title: str,
        body: str = "",
        variant: str = "default",
        sections: Optional[List[CardSection]] = None,
        image: Optional[str] = None,
        button: Optional[CardButton] = None,
    ):
        if variant not in self.VARIANTS:
            raise ValueError(f"Invalid variant '{variant}'. Must be one of {self.VARIANTS}")
        self.title = title
        self.body = body
        self.variant = variant
        self.sections = sections or []
        self.image = image
        self.button = button

    def to_dict(self) -> dict:
        d = {
            "type": "card",
            "title": self.title,
            "body": self.body,
            "variant": self.variant,
        }
        if self.sections:
            d["sections"] = [s.to_dict() for s in self.sections]
        if self.image:
            d["image"] = self.image
        if self.button:
            d["button"] = self.button.to_dict()
        return d


class AccordionItem:
    """A single expandable item within an Accordion."""

    def __init__(self, *, title: str, body: str):
        self.title = title
        self.body = body

    def to_dict(self) -> dict:
        return {"title": self.title, "body": self.body}


class Accordion:
    """An accordion component with collapsible items.

    Args:
        title: Accordion heading.
        items: List of AccordionItem entries.
    """

    def __init__(self, *, title: str, items: List[AccordionItem]):
        if not items:
            raise ValueError("Accordion must have at least one item")
        self.title = title
        self.items = items

    def to_dict(self) -> dict:
        return {
            "type": "accordion",
            "title": self.title,
            "items": [i.to_dict() for i in self.items],
        }
