#!/usr/bin/env python3
"""
Test Button parameters using card_framework via ModuleWrapper.

Tests all Button fields against the Google Chat webhook:
- text, icon (knownIcon, materialIcon)
- color (RGB), type (OUTLINED, FILLED, FILLED_TONAL, BORDERLESS)
- onClick (openLink), disabled, altText

Uses the wrapped module components (including custom components like Carousel)
instead of direct imports, demonstrating the full ModuleWrapper pipeline.
"""

import json
import os
import sys
import time

import httpx

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from gchat.card_framework_wrapper import get_card_framework_wrapper

WEBHOOK_URL = os.environ.get(
    "TEST_CHAT_WEBHOOK",
    "https://chat.googleapis.com/v1/spaces/AAQAKl_yP9Y/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Ie8-brhWHA9kE_2JiqKRDhqjadPHK4RNe15UcWwLXDA",
)


def snake_to_camel(s: str) -> str:
    """Convert snake_case to camelCase."""
    components = s.split("_")
    return components[0] + "".join(x.title() for x in components[1:])


def convert_keys_to_camel(obj):
    """Recursively convert dict keys from snake_case to camelCase."""
    if isinstance(obj, dict):
        return {snake_to_camel(k): convert_keys_to_camel(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [convert_keys_to_camel(item) for item in obj]
    return obj


class WrappedComponents:
    """
    Helper to access card_framework components via ModuleWrapper.

    Provides easy access to both standard and custom components.
    """

    def __init__(self):
        self.wrapper = get_card_framework_wrapper()
        self.module = self.wrapper.module
        self._cache = {}

    def get(self, name: str):
        """Get a component class by name."""
        if name in self._cache:
            return self._cache[name]

        # Search for the component
        results = self.wrapper.search(name, limit=1)
        if results and results[0].get("component"):
            cls = results[0]["component"]
            self._cache[name] = cls
            return cls

        # Try direct path lookup
        for path in [
            f"card_framework.v2.widgets.{name.lower()}.{name}",
            f"card_framework.v2.{name.lower()}.{name}",
            f"card_framework.v2.widgets.{name}",
            f"card_framework.v2.{name}",
        ]:
            cls = self.wrapper.get_component_by_path(path)
            if cls:
                self._cache[name] = cls
                return cls

        return None

    @property
    def Button(self):
        return self.get("Button")

    @property
    def ButtonList(self):
        return self.get("ButtonList")

    @property
    def Icon(self):
        return self.get("Icon")

    @property
    def Color(self):
        return self.get("Color")

    @property
    def OnClick(self):
        return self.get("OnClick")

    @property
    def OpenLink(self):
        return self.get("OpenLink")

    @property
    def TextParagraph(self):
        return self.get("TextParagraph")

    @property
    def DecoratedText(self):
        return self.get("DecoratedText")

    @property
    def Section(self):
        return self.get("Section")

    @property
    def Card(self):
        return self.get("Card")

    @property
    def CardHeader(self):
        return self.get("CardHeader")

    @property
    def Message(self):
        return self.get("Message")

    @property
    def CardWithId(self):
        """CardWithId is in card_framework.v2.card module."""
        if "CardWithId" not in self._cache:
            from card_framework.v2.card import CardWithId

            self._cache["CardWithId"] = CardWithId
        return self._cache["CardWithId"]

    # Custom components (registered via wrapper)
    @property
    def Carousel(self):
        return self.get("Carousel")

    @property
    def CarouselCard(self):
        return self.get("CarouselCard")

    @property
    def NestedWidget(self):
        return self.get("NestedWidget")

    def get_symbol(self, name: str) -> str:
        """Get the DSL symbol for a component."""
        return self.wrapper.symbol_mapping.get(name, "")


# Global instance
components = None


def get_components() -> WrappedComponents:
    """Get the wrapped components singleton."""
    global components
    if components is None:
        components = WrappedComponents()
    return components


def send_message(message, description: str = "") -> bool:
    """Render message and send to webhook."""
    print(f"\n{'=' * 60}")
    print(f"TEST: {description}")
    print(f"{'=' * 60}")

    # Render and convert to camelCase
    rendered = message.render()
    payload = convert_keys_to_camel(rendered)

    print(f"Payload preview: {json.dumps(payload, indent=2)[:400]}...")

    try:
        response = httpx.post(
            WEBHOOK_URL,
            json=payload,
            headers={"Content-Type": "application/json"},
            timeout=30.0,
        )

        if response.status_code == 200:
            print(f"✅ SUCCESS")
            return True
        else:
            print(f"❌ FAILED ({response.status_code})")
            print(f"Error: {response.text[:300]}")
            return False

    except Exception as e:
        print(f"❌ ERROR: {e}")
        return False


def test_button_types():
    """Test all Button type variants."""
    c = get_components()

    Button = c.Button
    ButtonList = c.ButtonList
    OnClick = c.OnClick
    OpenLink = c.OpenLink
    CardHeader = c.CardHeader
    Section = c.Section
    CardWithId = c.CardWithId
    Message = c.Message

    buttons = [
        Button(
            text="OUTLINED (default)",
            type_=Button.Type.OUTLINED,
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="FILLED",
            type_=Button.Type.FILLED,
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="FILLED_TONAL",
            type_=Button.Type.FILLED_TONAL,
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="BORDERLESS",
            type_=Button.Type.BORDERLESS,
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
    ]

    card = CardWithId(
        header=CardHeader(title="Button Types (Wrapped)", subtitle="Via ModuleWrapper"),
        sections=[Section(widgets=[ButtonList(buttons=buttons)])],
        _CardWithId__card_id="button-types-wrapped",
    )

    return send_message(Message(cards_v2=[card]), "Button Type Variants (Wrapped)")


def test_button_colors():
    """Test Button color parameter (forces FILLED type)."""
    c = get_components()

    Button = c.Button
    ButtonList = c.ButtonList
    Color = c.Color
    OnClick = c.OnClick
    OpenLink = c.OpenLink
    CardHeader = c.CardHeader
    Section = c.Section
    CardWithId = c.CardWithId
    Message = c.Message

    buttons = [
        Button(
            text="Red",
            color=Color(red=1.0, green=0.0, blue=0.0),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="Green",
            color=Color(red=0.0, green=0.7, blue=0.0),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="Blue",
            color=Color(red=0.0, green=0.4, blue=0.9),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="Purple",
            color=Color(red=0.6, green=0.2, blue=0.8),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
    ]

    card = CardWithId(
        header=CardHeader(
            title="Button Colors (Wrapped)", subtitle="RGB via ModuleWrapper"
        ),
        sections=[Section(widgets=[ButtonList(buttons=buttons)])],
        _CardWithId__card_id="button-colors-wrapped",
    )

    return send_message(Message(cards_v2=[card]), "Button Colors (Wrapped)")


def test_button_icons():
    """Test Button with knownIcon and materialIcon."""
    c = get_components()

    Button = c.Button
    ButtonList = c.ButtonList
    Icon = c.Icon
    OnClick = c.OnClick
    OpenLink = c.OpenLink
    CardHeader = c.CardHeader
    Section = c.Section
    CardWithId = c.CardWithId
    Message = c.Message

    buttons = [
        Button(
            text="Known: STAR",
            icon=Icon(known_icon=Icon.KnownIcon.STAR),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="Known: BOOKMARK",
            icon=Icon(known_icon=Icon.KnownIcon.BOOKMARK),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="Material: settings",
            icon=Icon(material_icon=Icon.MaterialIcon(name="settings")),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="Material: refresh",
            icon=Icon(material_icon=Icon.MaterialIcon(name="refresh")),
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
    ]

    card = CardWithId(
        header=CardHeader(title="Button Icons (Wrapped)", subtitle="Via ModuleWrapper"),
        sections=[Section(widgets=[ButtonList(buttons=buttons)])],
        _CardWithId__card_id="button-icons-wrapped",
    )

    return send_message(Message(cards_v2=[card]), "Button Icons (Wrapped)")


def test_button_states():
    """Test disabled and altText parameters."""
    c = get_components()

    Button = c.Button
    ButtonList = c.ButtonList
    OnClick = c.OnClick
    OpenLink = c.OpenLink
    CardHeader = c.CardHeader
    Section = c.Section
    CardWithId = c.CardWithId
    Message = c.Message

    buttons = [
        Button(
            text="Enabled",
            disabled=False,
            alt_text="This button is enabled and clickable",
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
        Button(
            text="Disabled",
            disabled=True,
            alt_text="This button is disabled",
            on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        ),
    ]

    card = CardWithId(
        header=CardHeader(
            title="Button States (Wrapped)", subtitle="Via ModuleWrapper"
        ),
        sections=[Section(widgets=[ButtonList(buttons=buttons)])],
        _CardWithId__card_id="button-states-wrapped",
    )

    return send_message(Message(cards_v2=[card]), "Button Disabled/AltText (Wrapped)")


def test_full_button():
    """Test Button with all parameters combined."""
    c = get_components()

    Button = c.Button
    ButtonList = c.ButtonList
    Icon = c.Icon
    Color = c.Color
    OnClick = c.OnClick
    OpenLink = c.OpenLink
    TextParagraph = c.TextParagraph
    CardHeader = c.CardHeader
    Section = c.Section
    CardWithId = c.CardWithId
    Message = c.Message

    btn = Button(
        text="Full Featured Button",
        icon=Icon(material_icon=Icon.MaterialIcon(name="rocket_launch")),
        color=Color(red=0.1, green=0.5, blue=0.8),
        on_click=OnClick(open_link=OpenLink(url="https://google.com")),
        disabled=False,
        alt_text="A fully configured button with icon, color, and link",
        type_=Button.Type.FILLED,
    )

    # Show DSL symbols for components used
    symbols_text = (
        f"Symbols: Button={c.get_symbol('Button')}, Icon={c.get_symbol('Icon')}"
    )

    card = CardWithId(
        header=CardHeader(
            title="Full Button (Wrapped)", subtitle="All params via ModuleWrapper"
        ),
        sections=[
            Section(
                widgets=[
                    TextParagraph(
                        text=f"<b>Button with all parameters:</b><br>{symbols_text}"
                    ),
                    ButtonList(buttons=[btn]),
                ]
            )
        ],
        _CardWithId__card_id="button-full-wrapped",
    )

    return send_message(Message(cards_v2=[card]), "Full Button Parameters (Wrapped)")


def test_wrapped_component_info():
    """Test that we can access component info from wrapper."""
    c = get_components()
    wrapper = c.wrapper

    # Show component info
    print("\n" + "=" * 60)
    print("WRAPPED COMPONENT INFO")
    print("=" * 60)

    components_to_check = ["Button", "Icon", "Color", "OnClick", "Section", "Card"]

    for name in components_to_check:
        cls = c.get(name)
        symbol = c.get_symbol(name)
        print(f"  {name}: {cls.__name__ if cls else 'NOT FOUND'} (symbol: {symbol})")

    # Check custom components
    print("\nCustom Components (Google Chat API only):")
    custom = ["Carousel", "CarouselCard", "NestedWidget"]
    for name in custom:
        symbol = c.get_symbol(name)
        # Custom components are registered but may not have Python classes
        print(f"  {name}: symbol={symbol}")

    return True


if __name__ == "__main__":
    print("=" * 60)
    print("BUTTON PARAMETERS TEST")
    print("Using ModuleWrapper for component access")
    print("=" * 60)

    # First show component info
    test_wrapped_component_info()

    tests = [
        test_button_types,
        test_button_colors,
        test_button_icons,
        test_button_states,
        test_full_button,
    ]

    results = []
    for test in tests:
        result = test()
        results.append((test.__name__, result))
        time.sleep(1)

    print("\n" + "=" * 60)
    print("SUMMARY")
    print("=" * 60)

    passed = sum(1 for _, r in results if r)
    failed = len(results) - passed

    for name, result in results:
        status = "✅" if result else "❌"
        print(f"  {status} {name}")

    print(f"\nTotal: {passed} passed, {failed} failed")
