# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/0-Card.ipynb.

# %% auto 0
__all__ = ['CHAT_DIV_ID', 'ChatCard', 'render_chat_list', 'mk_inp']

# %% ../../nbs/0-Card.ipynb 2
from fasthtml.common import *

# %% ../../nbs/0-Card.ipynb 4
class ChatCard:
    def __init__(
        self,
        user_color: str = "#1C0069",
        assistant_color: str = "#004539",
        user_emoji: str = "🗣️",
        assistant_emoji: str = "🕵️‍♂️",
        width: str = "60%",
        font_size: str = "1.5em",
        padding: str = "1.25em",
        border_radius: str = "1em",
        user_align: str = "right",
        assistant_align: str = "left",
        user_self_align: str = "center",
        assistant_self_align: str = "center",
        role_font_weight: str = "bold",
        role_font_size: str = "1.1em",
        role_margin_bottom: str = "8px",
        content_white_space: str = "pre-wrap",
        spinner_class: str = "spinner",
    ):
        self.colors = {
            "User": user_color,
            "Assistant": assistant_color,
        }

        self.emojis = {"User": user_emoji, "Assistant": assistant_emoji}

        self.alignments = {
            "User": {"text": user_align, "self": user_self_align},
            "Assistant": {"text": assistant_align, "self": assistant_self_align},
        }

        # Style configuration
        self.width = width
        self.font_size = font_size
        self.padding = padding
        self.border_radius = border_radius
        self.role_font_weight = role_font_weight
        self.role_font_size = role_font_size
        self.role_margin_bottom = role_margin_bottom
        self.content_white_space = content_white_space
        self.spinner_class = spinner_class

        # Build style template
        self.style_template = f"""
        background: {{bg}}; color: {{text_color}}; padding: 10px; font-size: {self.font_size}; 
        width: {self.width}; align-self: {{self_align}}; 
        text-align: {{text_align}}; border-radius: {self.border_radius}; 
        padding: {self.padding}"""

    def _get_text_color(self, bg_color: str) -> str:
        """
        Calculate whether to use black or white text based on background color luminance.
        Uses the relative luminance formula from WCAG guidelines.
        """
        # Remove # if present
        hex_color = bg_color.lstrip("#")

        # Convert hex to RGB
        r = int(hex_color[0:2], 16) / 255.0
        g = int(hex_color[2:4], 16) / 255.0
        b = int(hex_color[4:6], 16) / 255.0

        # Calculate relative luminance
        def adjust_channel(c):
            return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4

        r, g, b = adjust_channel(r), adjust_channel(g), adjust_channel(b)
        luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b

        # Return white for dark backgrounds, black for light backgrounds
        return "#FFFFFF" if luminance < 0.5 else "#000000"

    def _get_style(self, role: str) -> str:
        """Generate CSS style string for a given role."""
        bg_color = self.colors[role]
        return self.style_template.format(
            bg=bg_color,
            text_color=self._get_text_color(bg_color),
            self_align=self.alignments[role]["self"],
            text_align=self.alignments[role]["text"],
        )

    def _get_role_style(self) -> str:
        """Generate CSS style string for role labels."""
        return f"font-weight: {self.role_font_weight}; font-size: {self.role_font_size}; display: block; margin-bottom: {self.role_margin_bottom};"

    def render(self, data: dict):
        """
        Render a chat card with the given data.

        Args:
            data: Dictionary containing:
                - role: "User" or "Assistant"
                - content: Message content (optional)
                - pending: Boolean indicating if message is loading (optional)

        Returns:
            FastHTML Div element representing the chat card
        """
        role = data["role"]
        content = data.get("content", "")
        pending = data.get("pending", False)

        style = self._get_style(role)
        emoji = self.emojis[role]

        if pending:
            spinner = Span(cls=self.spinner_class)
            return Div(f"{emoji} {role}: ", spinner, style=style)

        # Add 'marked' class to enable markdown rendering
        return Div(
            Span(
                U(f"{emoji} {role}: "),
                style=self._get_role_style(),
            ),
            Div(
                content, cls="marked", style=f"white-space: {self.content_white_space};"
            ),
            style=style,
        )

    def __call__(self, data: dict):
        """Make the class callable like the original function."""
        return self.render(data)

# %% ../../nbs/0-Card.ipynb 7
CHAT_DIV_ID = "chat-cards"


def render_chat_list(messages: List[Dict[str, str]], ChatCard: ChatCard):
    return Div(
        *[ChatCard(m) for m in messages],
        id=CHAT_DIV_ID,
        cls="chat-cards",
        style="display: flex; flex-direction: column; gap: 10px;",
    )

# %% ../../nbs/0-Card.ipynb 9
def mk_inp():
    return Input(
        id="msg",
        placeholder="Type a message...",
        autofocus=True,
        style="width: 60%; max-width: 600px; padding: 0.75em; font-size: 1em; border-radius: 0.5em",
    )
