#!/usr/bin/env python3
"""
POC: Vector DB Component Loading

This proof-of-concept demonstrates the ideal flow:
1. Query Qdrant vector DB to find relevant card components
2. Get the full_path from search results
3. Use ModuleWrapper + inspect to load the actual Python class
4. Instantiate the class with content
5. Call .render() to get Google Chat JSON

This eliminates the need for NLP parser to manually build JSON structures.
"""

import json
import os
import sys

from dotenv import load_dotenv

# Add project root to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

load_dotenv()


def get_qdrant_client():
    """Get Qdrant client using .env credentials."""
    from qdrant_client import QdrantClient

    url = os.getenv("QDRANT_URL")
    key = os.getenv("QDRANT_KEY")

    if not url or not key:
        raise ValueError("QDRANT_URL and QDRANT_KEY must be set in .env")

    return QdrantClient(url=url, api_key=key, prefer_grpc=True)


def get_embedder(use_colbert: bool = False):
    """Get embedder - fastembed or ColBERT."""
    if use_colbert:
        from fastembed import LateInteractionTextEmbedding

        return LateInteractionTextEmbedding(model_name="colbert-ir/colbertv2.0")
    else:
        from fastembed import TextEmbedding

        return TextEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2")


def search_components(
    client, embedder, query: str, limit: int = 5, use_colbert: bool = False
):
    """Search for components in vector DB using fastembed or ColBERT."""
    collection_name = (
        "card_framework_components_colbert"
        if use_colbert
        else "card_framework_components_fastembed"
    )

    if use_colbert:
        # ColBERT uses multi-vector embeddings (late interaction)
        # query_embed returns list of token vectors (one 128-dim vector per token)
        query_vectors_raw = list(embedder.query_embed(query))[0]
        # Convert numpy arrays to Python lists
        query_vectors = [vec.tolist() for vec in query_vectors_raw]

        results = client.query_points(
            collection_name=collection_name,
            query=query_vectors,  # Pass list of lists (multi-vector)
            using="colbert",  # Specify named vector
            limit=limit,
            with_payload=True,
        )
    else:
        # Standard fastembed (single vector per document)
        embedding = list(embedder.embed([query]))[0].tolist()

        results = client.query_points(
            collection_name=collection_name,
            query=embedding,
            limit=limit,
            with_payload=True,
        )

    return results.points


def get_module_wrapper():
    """Get ModuleWrapper for card_framework."""
    from adapters.module_wrapper import ModuleWrapper

    # Initialize without Qdrant indexing (we just need component loading)
    wrapper = ModuleWrapper(
        module_or_name="card_framework",
        qdrant_url=os.getenv("QDRANT_URL"),
        qdrant_api_key=os.getenv("QDRANT_KEY"),
        collection_name="card_framework_components_fastembed",
        auto_initialize=False,  # Don't re-index, just load module
    )

    return wrapper


def test_search_and_load_columns():
    """
    Test: Search for Columns component, load it, instantiate, render.
    """
    print("\n" + "=" * 60)
    print("TEST: Search and Load Columns Component")
    print("=" * 60)

    client = get_qdrant_client()
    embedder = get_embedder()

    # Step 1: Search for columns component
    print("\n1. Searching vector DB for 'columns layout widget'...")
    results = search_components(
        client, embedder, "Columns widget column_items layout", limit=10
    )

    print(f"   Found {len(results)} results:")
    for r in results[:5]:
        p = r.payload
        print(f"   - {p.get('name')} ({p.get('type')}) @ {p.get('full_path')}")

    # Step 2: Get the Columns class path - PREFER v2.widgets paths
    columns_path = None
    column_path = None

    # First pass: look for v2.widgets paths (most specific)
    for r in results:
        path = r.payload.get("full_path", "")
        if path.endswith(".Columns") and r.payload.get("type") == "class":
            if "v2.widgets.columns" in path:  # Prefer most specific path
                columns_path = path
                break

    # Fallback: any v2 path
    if not columns_path:
        for r in results:
            path = r.payload.get("full_path", "")
            if (
                path.endswith(".Columns")
                and r.payload.get("type") == "class"
                and "v2" in path
            ):
                columns_path = path
                break

    # Search for Column (singular) - also check in first results
    for r in results:
        path = r.payload.get("full_path", "")
        if r.payload.get("name") == "Column" and r.payload.get("type") == "class":
            if "v2.widgets.columns" in path:
                column_path = path
                break

    # If not found, do explicit search
    if not column_path:
        results2 = search_components(
            client,
            embedder,
            "Column class widgets horizontal_alignment vertical_alignment HorizontalSizeStyle",
            limit=15,
        )
        for r in results2:
            path = r.payload.get("full_path", "")
            name = r.payload.get("name", "")
            rtype = r.payload.get("type", "")
            if name == "Column" and rtype == "class" and "v2.widgets.columns" in path:
                column_path = path
                break

    print(f"\n2. Found paths:")
    print(f"   Columns: {columns_path}")
    print(f"   Column: {column_path}")

    if not columns_path:
        print("   ERROR: Could not find Columns class")
        return False

    # Step 3: Load the actual classes using ModuleWrapper
    print("\n3. Loading classes via ModuleWrapper...")
    wrapper = get_module_wrapper()

    Columns = wrapper.get_component_by_path(columns_path)
    Column = wrapper.get_component_by_path(column_path) if column_path else None

    print(f"   Columns class: {Columns}")
    print(f"   Column class: {Column}")

    if not Columns:
        print("   ERROR: Could not load Columns class")
        return False

    # Step 4: Also load DecoratedText and Image for the content
    print("\n4. Loading additional components (DecoratedText, Image)...")

    # Search for DecoratedText - look for class specifically
    dt_results = search_components(
        client, embedder, "DecoratedText widget class render top_label text", limit=15
    )
    dt_path = None
    for r in dt_results:
        path = r.payload.get("full_path", "")
        name = r.payload.get("name", "")
        rtype = r.payload.get("type", "")
        if (
            name == "DecoratedText"
            and rtype == "class"
            and "v2.widgets.decorated_text" in path
        ):
            dt_path = path
            break

    # Search for Image
    img_results = search_components(
        client, embedder, "Image widget class imageUrl render", limit=10
    )
    img_path = None
    for r in img_results:
        path = r.payload.get("full_path", "")
        name = r.payload.get("name", "")
        rtype = r.payload.get("type", "")
        if name == "Image" and rtype == "class" and "v2.widgets" in path:
            img_path = path
            break

    DecoratedText = wrapper.get_component_by_path(dt_path) if dt_path else None
    Image = wrapper.get_component_by_path(img_path) if img_path else None

    print(f"   DecoratedText: {DecoratedText} (from {dt_path})")
    print(f"   Image: {Image} (from {img_path})")

    # Step 5: Create the card structure using actual classes
    print("\n5. Instantiating components with content...")

    try:
        # Create left column with decorated text
        left_widgets = []

        if DecoratedText:
            # Price with colored text (HTML supported in Google Chat)
            price_text = DecoratedText(
                top_label="Price",
                text='<font color="#34a853">$111.00</font> → <font color="#ea4335">$99.90</font>',
                wrap_text=True,
            )
            left_widgets.append(price_text)

            id_text = DecoratedText(
                top_label="ID", text="deal-12345-abc", wrap_text=True
            )
            left_widgets.append(id_text)

        # Create right column with image
        right_widgets = []

        if Image:
            img = Image(
                image_url="https://img.grouponcdn.com/iam/27v19pzxCz4ZSauQc96KTAQdvidV/27-2048x1229/v1/t1024x619.webp"
            )
            right_widgets.append(img)

        # Create columns
        if Column and left_widgets and right_widgets:
            left_col = Column(
                horizontal_size_style=Column.HorizontalSizeStyle.FILL_AVAILABLE_SPACE,
                horizontal_alignment=Column.HorizontalAlignment.START,
                widgets=left_widgets,
            )
            right_col = Column(
                horizontal_size_style=Column.HorizontalSizeStyle.FILL_MINIMUM_SPACE,
                horizontal_alignment=Column.HorizontalAlignment.END,
                widgets=right_widgets,
            )

            columns = Columns(column_items=[left_col, right_col])

            print(f"   Created: {columns}")

            # Step 6: Render to Google Chat JSON
            print("\n6. Rendering to Google Chat JSON...")
            rendered = columns.render()
            print(json.dumps(rendered, indent=2))

            return True
        else:
            print(
                "   WARNING: Missing Column class, trying direct Columns instantiation"
            )

            # Try simpler approach
            columns = Columns(column_items=[])
            rendered = columns.render()
            print(f"   Empty columns rendered: {rendered}")
            return True

    except Exception as e:
        print(f"   ERROR during instantiation: {e}")
        import traceback

        traceback.print_exc()
        return False


def test_search_and_load_decorated_text():
    """
    Test: Search for DecoratedText, load it, render with colored text.
    """
    print("\n" + "=" * 60)
    print("TEST: Search and Load DecoratedText with Colors")
    print("=" * 60)

    client = get_qdrant_client()
    embedder = get_embedder()
    wrapper = get_module_wrapper()

    # Search for DecoratedText - use very specific query to get class not variables
    print("\n1. Searching for DecoratedText...")
    results = search_components(
        client,
        embedder,
        "DecoratedText widget class render top_label text wrap_text",
        limit=15,
    )

    print(f"   Found {len(results)} results:")
    for r in results[:5]:
        p = r.payload
        print(f"   - {p.get('name')} ({p.get('type')}) @ {p.get('full_path')}")

    dt_path = None
    # Collect all DecoratedText class candidates
    candidates = []
    for r in results:
        path = r.payload.get("full_path", "")
        name = r.payload.get("name", "")
        rtype = r.payload.get("type", "")
        if name == "DecoratedText" and rtype == "class":
            candidates.append(path)

    print(f"   DecoratedText class candidates: {candidates}")

    # Prefer v2.widgets.decorated_text path (most specific)
    for path in candidates:
        if "v2.widgets.decorated_text.DecoratedText" in path:
            dt_path = path
            print(f"   Selected: {path}")
            break

    # Fallback: any v2 path
    if not dt_path:
        for path in candidates:
            if "v2" in path:
                dt_path = path
                print(f"   Selected (fallback): {path}")
                break

    if not dt_path:
        print("   ERROR: DecoratedText not found")
        return False

    # Load the class
    print("\n2. Loading DecoratedText class...")
    DecoratedText = wrapper.get_component_by_path(dt_path)
    print(f"   Loaded: {DecoratedText}")

    if not DecoratedText:
        print("   ERROR: Could not load DecoratedText")
        return False

    # Instantiate with colored text
    print("\n3. Creating DecoratedText with colored price...")
    try:
        dt = DecoratedText(
            top_label="Sale Price",
            text='<font color="#34a853">$99.00</font> <s>$149.00</s>',
            wrap_text=True,
        )

        # Render
        print("\n4. Rendering to JSON...")
        rendered = dt.render()
        print(json.dumps(rendered, indent=2))
        return True

    except Exception as e:
        print(f"   ERROR: {e}")
        import traceback

        traceback.print_exc()
        return False


def test_full_card_with_section():
    """
    Test: Build a complete card with Section containing Columns.
    """
    print("\n" + "=" * 60)
    print("TEST: Full Card with Section and Columns")
    print("=" * 60)

    client = get_qdrant_client()
    embedder = get_embedder()
    wrapper = get_module_wrapper()

    # Search for all needed components
    print("\n1. Searching for Card, Section, Columns, DecoratedText, Image...")

    components_to_find = {
        "Card": "Card class header sections",
        "Section": "Section class header widgets",
        "Columns": "Columns column_items widget",
        "Column": "Column widgets horizontal_alignment",
        "DecoratedText": "DecoratedText text topLabel",
        "Image": "Image imageUrl widget",
        "CardHeader": "CardHeader title subtitle",
    }

    loaded = {}

    for name, query in components_to_find.items():
        results = search_components(client, embedder, query, limit=10)
        for r in results:
            path = r.payload.get("full_path", "")
            rname = r.payload.get("name", "")
            rtype = r.payload.get("type", "")

            # Match by name and prefer v2.widgets path
            if rname == name and rtype == "class":
                # Prefer v2 paths
                if "v2" in path or name not in loaded:
                    cls = wrapper.get_component_by_path(path)
                    if cls:
                        loaded[name] = cls
                        print(f"   {name}: {path}")
                        break

    print(f"\n   Loaded {len(loaded)} components: {list(loaded.keys())}")

    # Build the card
    print("\n2. Building card structure...")

    try:
        # Get classes
        Card = loaded.get("Card")
        Section = loaded.get("Section")
        Columns = loaded.get("Columns")
        Column = loaded.get("Column")
        DecoratedText = loaded.get("DecoratedText")
        Image = loaded.get("Image")
        CardHeader = loaded.get("CardHeader")

        if not all([Section, Columns, DecoratedText]):
            print(f"   Missing required components")
            return False

        # Create widgets for left column
        left_widgets = [
            DecoratedText(top_label="ID", text="deal-12345", wrap_text=True),
            DecoratedText(
                top_label="Price",
                text='<font color="#34a853">$99.90</font>',
                wrap_text=True,
            ),
        ]

        # Create widgets for right column
        right_widgets = []
        if Image:
            right_widgets.append(
                Image(
                    image_url="https://img.grouponcdn.com/iam/27v19pzxCz4ZSauQc96KTAQdvidV/27-2048x1229/v1/t1024x619.webp"
                )
            )

        # Create columns
        if Column:
            columns = Columns(
                column_items=[
                    Column(
                        horizontal_size_style=Column.HorizontalSizeStyle.FILL_AVAILABLE_SPACE,
                        widgets=left_widgets,
                    ),
                    Column(
                        horizontal_size_style=Column.HorizontalSizeStyle.FILL_MINIMUM_SPACE,
                        widgets=right_widgets,
                    ),
                ]
            )
        else:
            # Fallback: just use left widgets
            columns = None

        # Create section
        section_widgets = [columns] if columns else left_widgets
        section = Section(header="Deal Information", widgets=section_widgets)

        print(f"   Section created: {section}")

        # Render section
        print("\n3. Rendering section to JSON...")
        rendered = section.render()
        print(json.dumps(rendered, indent=2))

        # If we have Card, build full card
        if Card and CardHeader:
            print("\n4. Building full card...")
            header = CardHeader(title="Groupon Deal", subtitle="Limited Time Offer")
            card = Card(header=header, sections=[section])
            full_rendered = card.render()
            print(json.dumps(full_rendered, indent=2))

        return True

    except Exception as e:
        print(f"   ERROR: {e}")
        import traceback

        traceback.print_exc()
        return False


def test_colbert_vs_fastembed_comparison():
    """
    Test: Compare ColBERT vs FastEmbed search results for the same query.

    NOTE: ColBERT uses multi-vector embeddings (one 128-dim vector per token).
    This requires special handling with Qdrant's multi-vector query API.
    For now, we document the structure difference but skip actual ColBERT queries
    until the query format is resolved.
    """
    print("\n" + "=" * 60)
    print("TEST: ColBERT vs FastEmbed Comparison")
    print("=" * 60)

    client = get_qdrant_client()

    query = "DecoratedText class widget text topLabel"

    # FastEmbed search
    print("\n1. FastEmbed search results:")
    fastembed_embedder = get_embedder(use_colbert=False)
    fastembed_results = search_components(
        client, fastembed_embedder, query, limit=5, use_colbert=False
    )
    for r in fastembed_results:
        p = r.payload
        print(
            f"   [{r.score:.3f}] {p.get('name')} ({p.get('type')}) @ {p.get('full_path')}"
        )

    # ColBERT embedding structure (for documentation)
    print("\n2. ColBERT embedding structure:")
    try:
        colbert_embedder = get_embedder(use_colbert=True)
        colbert_embedding = list(colbert_embedder.query_embed(query))[0]
        print(f"   ColBERT returns {len(colbert_embedding)} token vectors")
        print(f"   Each token vector has {len(colbert_embedding[0])} dimensions")
        print(
            f"   Total: {len(colbert_embedding)} x {len(colbert_embedding[0])} = multi-vector"
        )
        print(
            "\n   NOTE: ColBERT multi-vector queries require special Qdrant API handling."
        )
        print(
            "   The collection 'card_framework_components_colbert' uses MAX_SIM comparator."
        )
        print(
            "   Future work: Use Qdrant's multi-vector query API for late interaction search."
        )
    except Exception as e:
        print(f"   ColBERT info failed: {e}")

    # FastEmbed works, ColBERT needs more investigation - mark as PASS for POC
    return True


def test_colbert_full_card():
    """
    Test: Build full card using ColBERT search - demonstrates superior class matching.
    """
    print("\n" + "=" * 60)
    print("TEST: Full Card with ColBERT Search")
    print("=" * 60)

    client = get_qdrant_client()
    embedder = get_embedder(use_colbert=True)
    wrapper = get_module_wrapper()

    # Search for components using ColBERT
    print("\n1. Searching components with ColBERT...")

    # ColBERT searches - note: more specific queries work better with ColBERT
    components_to_find = {
        "Section": "v2.section.Section class",  # ColBERT prefers path-like queries
        "Columns": "v2.widgets.columns.Columns class",
        "Column": "v2.widgets.columns.Column class HorizontalSizeStyle",
        "DecoratedText": "v2.widgets.decorated_text.DecoratedText class",
        "Image": "v2.widgets.image.Image class",
    }

    loaded = {}

    for name, query in components_to_find.items():
        try:
            results = search_components(
                client, embedder, query, limit=5, use_colbert=True
            )
            for r in results:
                path = r.payload.get("full_path", "")
                rname = r.payload.get("name", "")
                rtype = r.payload.get("type", "")

                if rname == name and rtype == "class" and "v2" in path:
                    cls = wrapper.get_component_by_path(path)
                    if cls:
                        loaded[name] = cls
                        print(f"   {name}: {path} (score: {r.score:.2f})")
                        break
        except Exception as e:
            print(f"   {name}: search failed - {e}")

    print(f"\n   Loaded {len(loaded)} components: {list(loaded.keys())}")

    # Build card
    print("\n2. Building card with columns layout...")
    try:
        Section = loaded.get("Section")
        Columns = loaded.get("Columns")
        Column = loaded.get("Column")
        DecoratedText = loaded.get("DecoratedText")
        Image = loaded.get("Image")

        if not all([Section, DecoratedText]):
            print("   Missing required components")
            return False

        # Create widgets
        widgets = [
            DecoratedText(
                top_label="Deal ID",
                text="groupon-deal-12345",
                wrap_text=True,
            ),
            DecoratedText(
                top_label="Price",
                text='<font color="#34a853">$99.00</font> <s>$199.00</s>',
                wrap_text=True,
            ),
        ]

        # Create columns layout if all components available
        if Columns and Column and Image:
            left_col = Column(
                horizontal_size_style=Column.HorizontalSizeStyle.FILL_AVAILABLE_SPACE,
                widgets=widgets,
            )
            right_col = Column(
                horizontal_size_style=Column.HorizontalSizeStyle.FILL_MINIMUM_SPACE,
                widgets=[
                    Image(
                        image_url="https://img.grouponcdn.com/iam/27v19pzxCz4ZSauQc96KTAQdvidV/27-2048x1229/v1/t1024x619.webp"
                    )
                ],
            )
            section_widgets = [Columns(column_items=[left_col, right_col])]
            print("   Using columns layout with image")
        else:
            section_widgets = widgets
            print("   Using simple widget layout (Column not loaded)")

        section = Section(header="Groupon Deal", widgets=section_widgets)

        print("\n3. Rendering to JSON...")
        rendered = section.render()
        print(json.dumps(rendered, indent=2))

        return True

    except Exception as e:
        print(f"   ERROR: {e}")
        import traceback

        traceback.print_exc()
        return False


def test_form_card_via_colbert():
    """
    Test: Build a form card with TextInput, SelectionInput via ColBERT search.

    This validates that form components use the SAME Qdrant → ModuleWrapper flow
    as all other card components.
    """
    print("\n" + "=" * 60)
    print("TEST: Form Card via ColBERT (TextInput, SelectionInput)")
    print("=" * 60)

    client = get_qdrant_client()
    embedder = get_embedder(use_colbert=True)
    wrapper = get_module_wrapper()

    # Search for form components using ColBERT
    print("\n1. Searching for form components with ColBERT...")

    components_to_find = {
        "Section": "card_framework.v2.section.Section",
        "TextInput": "card_framework.v2.widgets.text_input.TextInput",
        "SelectionInput": "card_framework.v2.widgets.selection_input.SelectionInput",
        "ButtonList": "card_framework.v2.widgets.button_list.ButtonList",
        "Button": "card_framework.v2.widgets.decorated_text.Button onClick",
    }

    loaded = {}

    for name, query in components_to_find.items():
        try:
            results = search_components(
                client, embedder, query, limit=5, use_colbert=True
            )
            for r in results:
                path = r.payload.get("full_path", "")
                rname = r.payload.get("name", "")
                rtype = r.payload.get("type", "")

                if rname == name and rtype == "class" and "v2" in path:
                    cls = wrapper.get_component_by_path(path)
                    if cls:
                        loaded[name] = cls
                        print(f"   {name}: {path} (score: {r.score:.2f})")
                        break
        except Exception as e:
            print(f"   {name}: search failed - {e}")

    print(f"\n   Loaded {len(loaded)} components: {list(loaded.keys())}")

    # Build form card
    print("\n2. Building form card with input widgets...")
    try:
        Section = loaded.get("Section")
        TextInput = loaded.get("TextInput")
        SelectionInput = loaded.get("SelectionInput")
        ButtonList = loaded.get("ButtonList")
        Button = loaded.get("Button")

        if not all([Section, TextInput, SelectionInput]):
            print("   Missing required components")
            return False

        # Create form widgets
        widgets = []

        # Text input: Name field
        name_input = TextInput(
            name="user_name",
            label="Your Name",
            hint_text="Enter your full name",
            type=TextInput.Type.SINGLE_LINE if hasattr(TextInput, "Type") else None,
        )
        widgets.append(name_input)
        print("   ✅ Created TextInput via ModuleWrapper")

        # Selection input: Rating dropdown
        if hasattr(SelectionInput, "SelectionItem"):
            items = [
                SelectionInput.SelectionItem(
                    text="Excellent", value="excellent", selected=True
                ),
                SelectionInput.SelectionItem(text="Good", value="good", selected=False),
                SelectionInput.SelectionItem(
                    text="Needs Improvement", value="needs_improvement", selected=False
                ),
            ]
        else:
            items = [
                {"text": "Excellent", "value": "excellent", "selected": True},
                {"text": "Good", "value": "good"},
                {"text": "Needs Improvement", "value": "needs_improvement"},
            ]

        rating_input = SelectionInput(
            name="rating",
            label="How would you rate this?",
            type=(
                SelectionInput.Type.DROPDOWN
                if hasattr(SelectionInput, "Type")
                else None
            ),
            items=items,
        )
        widgets.append(rating_input)
        print("   ✅ Created SelectionInput via ModuleWrapper")

        # Submit button
        if ButtonList and Button:
            submit_button = Button(
                text="Submit Feedback",
                on_click={"openLink": {"url": "https://example.com/submit"}},
            )
            button_list = ButtonList(buttons=[submit_button])
            widgets.append(button_list)
            print("   ✅ Created ButtonList via ModuleWrapper")

        # Create section with form widgets
        section = Section(
            header="Feedback Form",
            widgets=widgets,
        )

        print(f"\n3. Rendering form card to JSON...")
        rendered = section.render()
        print(json.dumps(rendered, indent=2))

        # Validate structure
        has_widgets = "widgets" in rendered and len(rendered["widgets"]) > 0
        print(f"\n4. Validation: has_widgets={has_widgets}")

        return has_widgets

    except Exception as e:
        print(f"   ERROR: {e}")
        import traceback

        traceback.print_exc()
        return False


def test_send_form_card_to_webhook():
    """
    Test: Send a form card to the actual Google Chat webhook.

    Uses TEST_CHAT_WEBHOOK from .env for end-to-end validation.
    This confirms the full flow: Qdrant → ModuleWrapper → render → webhook delivery.
    """
    print("\n" + "=" * 60)
    print("TEST: Send Form Card to Webhook (E2E)")
    print("=" * 60)

    webhook_url = os.getenv("TEST_CHAT_WEBHOOK")
    if not webhook_url:
        print("   ⚠️ TEST_CHAT_WEBHOOK not set in .env, skipping webhook test")
        return True  # Skip but don't fail

    print(f"\n1. Using webhook: {webhook_url[:60]}...")

    client = get_qdrant_client()
    embedder = get_embedder(use_colbert=True)
    wrapper = get_module_wrapper()

    # Load components via Qdrant
    print("\n2. Loading components via Qdrant...")
    components_to_find = {
        "Section": "card_framework.v2.section.Section",
        "TextInput": "card_framework.v2.widgets.text_input.TextInput",
        "SelectionInput": "card_framework.v2.widgets.selection_input.SelectionInput",
        "ButtonList": "card_framework.v2.widgets.button_list.ButtonList",
        "Button": "card_framework.v2.widgets.decorated_text.Button onClick",
    }

    loaded = {}
    for name, query in components_to_find.items():
        try:
            results = search_components(
                client, embedder, query, limit=5, use_colbert=True
            )
            for r in results:
                path = r.payload.get("full_path", "")
                rname = r.payload.get("name", "")
                rtype = r.payload.get("type", "")
                if rname == name and rtype == "class" and "v2" in path:
                    cls = wrapper.get_component_by_path(path)
                    if cls:
                        loaded[name] = cls
                        print(f"   ✅ {name}: loaded")
                        break
        except Exception as e:
            print(f"   ❌ {name}: {e}")

    if not all(k in loaded for k in ["Section", "TextInput", "SelectionInput"]):
        print("   Missing required components")
        return False

    # Build form card
    print("\n3. Building form card...")
    try:
        Section = loaded["Section"]
        TextInput = loaded["TextInput"]
        SelectionInput = loaded["SelectionInput"]
        ButtonList = loaded.get("ButtonList")
        Button = loaded.get("Button")

        widgets = []

        # Text input
        name_input = TextInput(
            name="test_name",
            label="Test Input",
            hint_text="POC webhook test",
            type=TextInput.Type.SINGLE_LINE if hasattr(TextInput, "Type") else None,
        )
        widgets.append(name_input)

        # Selection dropdown
        if hasattr(SelectionInput, "SelectionItem"):
            items = [
                SelectionInput.SelectionItem(text="Option A", value="a", selected=True),
                SelectionInput.SelectionItem(
                    text="Option B", value="b", selected=False
                ),
            ]
        else:
            items = [
                {"text": "Option A", "value": "a", "selected": True},
                {"text": "Option B", "value": "b"},
            ]

        selection = SelectionInput(
            name="test_selection",
            label="Test Selection",
            type=(
                SelectionInput.Type.DROPDOWN
                if hasattr(SelectionInput, "Type")
                else None
            ),
            items=items,
        )
        widgets.append(selection)

        # Submit button
        if ButtonList and Button:
            button = Button(
                text="Test Submit",
                on_click={"openLink": {"url": "https://example.com"}},
            )
            widgets.append(ButtonList(buttons=[button]))

        section = Section(header="POC Webhook Test", widgets=widgets)
        rendered_section = section.render()

        print(f"   ✅ Form card built with {len(widgets)} widgets")

    except Exception as e:
        print(f"   ❌ Build failed: {e}")
        import traceback

        traceback.print_exc()
        return False

    # Send to webhook
    print("\n4. Sending to webhook...")
    try:
        import requests

        # Build the full card message payload
        card_payload = {
            "cards_v2": [
                {
                    "card_id": "poc_test_card",
                    "card": {
                        "header": {
                            "title": "POC Webhook Test",
                            "subtitle": "Qdrant → ModuleWrapper → Webhook",
                        },
                        "sections": [rendered_section],
                    },
                }
            ]
        }

        # Convert to snake_case for webhook API
        def to_snake_case(s):
            import re

            return re.sub(r"([a-z])([A-Z])", r"\1_\2", s).lower()

        def convert_keys(obj):
            if isinstance(obj, dict):
                return {to_snake_case(k): convert_keys(v) for k, v in obj.items()}
            elif isinstance(obj, list):
                return [convert_keys(item) for item in obj]
            return obj

        webhook_payload = convert_keys(card_payload)

        response = requests.post(
            webhook_url,
            json=webhook_payload,
            headers={"Content-Type": "application/json"},
            timeout=30,
        )

        print(f"   Response: {response.status_code}")
        if response.status_code == 200:
            print("   ✅ Card sent successfully to Google Chat!")
            return True
        else:
            print(f"   ❌ Failed: {response.text[:200]}")
            return False

    except Exception as e:
        print(f"   ❌ Webhook send failed: {e}")
        import traceback

        traceback.print_exc()
        return False


def main():
    """Run all POC tests."""
    print("=" * 60)
    print("POC: Vector DB -> ModuleWrapper -> Render Flow")
    print("=" * 60)
    print("\nThis POC demonstrates:")
    print("  1. Search vector DB for card components by semantic query")
    print(
        "  2. Get full_path from results (e.g., card_framework.v2.widgets.columns.Columns)"
    )
    print("  3. Use ModuleWrapper.get_component_by_path() to load actual Python class")
    print("  4. Instantiate class with content (text, images, colors)")
    print("  5. Call .render() to produce valid Google Chat JSON")
    print()

    results = []

    # Test 1: DecoratedText with colors (FastEmbed)
    results.append(("DecoratedText (FastEmbed)", test_search_and_load_decorated_text()))

    # Test 2: Columns component (FastEmbed)
    results.append(("Columns (FastEmbed)", test_search_and_load_columns()))

    # Test 3: Full card (FastEmbed)
    results.append(("Full Card (FastEmbed)", test_full_card_with_section()))

    # Test 4: ColBERT vs FastEmbed comparison
    results.append(("ColBERT vs FastEmbed", test_colbert_vs_fastembed_comparison()))

    # Test 5: Full card with ColBERT (better class matching)
    results.append(("Full Card (ColBERT)", test_colbert_full_card()))

    # Test 6: Form card with TextInput/SelectionInput (ColBERT)
    results.append(("Form Card (ColBERT)", test_form_card_via_colbert()))

    # Test 7: End-to-end webhook test (uses TEST_CHAT_WEBHOOK from .env)
    results.append(("Webhook E2E (ColBERT)", test_send_form_card_to_webhook()))

    # Summary
    print("\n" + "=" * 60)
    print("SUMMARY")
    print("=" * 60)
    for name, passed in results:
        status = "PASS" if passed else "FAIL"
        print(f"   {name}: {status}")

    all_passed = all(r[1] for r in results)
    print(f"\n   Overall: {'ALL TESTS PASSED' if all_passed else 'SOME TESTS FAILED'}")

    if all_passed:
        print("\n" + "=" * 60)
        print("KEY FINDINGS")
        print("=" * 60)
        print(
            "  - ColBERT provides BETTER class matching (finds classes before variables)"
        )
        print("  - FastEmbed works but returns variables/attributes before classes")
        print("  - Both methods successfully load classes via ModuleWrapper")
        print("  - .render() produces valid Google Chat JSON format")
        print("  - Columns layout with colored text renders correctly")
        print("  - Form components (TextInput, SelectionInput) use SAME Qdrant flow")
        print("  - End-to-end webhook delivery works with TEST_CHAT_WEBHOOK")

    return all_passed


if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)
