import os
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent.parent))  # run from repo root

import logging

from azure.communication.messages.aio import NotificationMessagesClient
from dotenv import load_dotenv

from whatsapp import Bot
from whatsapp.bindings.azure import AzureBindingClient
from whatsapp.messages import (
    ActionGroup,
    ActionGroupItem,
    AudioMessage,
    ButtonItem,
    DocumentMessage,
    ImageMessage,
    InteractiveButtonMessage,
    InteractiveListMessage,
    InteractiveUrlMessage,
    ReactionMessage,
    StickerMessage,
    TextMessage,
    VideoMessage,
)
from whatsapp.messages.dialogs import Dialog, DialogContext, DialogTurnResult, DialogTurnStatus

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

load_dotenv()

# mute azure logs
logging.getLogger("azure.core.pipeline.policies.http_logging_policy").setLevel(logging.WARNING)


@Dialog.set(name="RichMessagesDialog", main=True)
class RichMessagesDialog(Dialog):
    """
    A dialog that demonstrates all supported message types.
    Guides the user through different message capabilities.
    """

    @Dialog.step()
    async def welcome(self, dc: DialogContext):
        """Welcome message and show menu."""
        message = TextMessage(
            ctx=dc.ctx, message="👋 Welcome to the Rich Messages Demo! Let me show you what I can do."
        )
        await dc.message.send(message)
        await dc.continue_dialog()

    @Dialog.step()
    @Dialog.store("selected_option")
    async def show_menu(self, dc: DialogContext):
        """Display interactive menu of message types."""
        groups = [
            ActionGroup(
                title="📱 Basic Messages",
                items=[
                    ActionGroupItem("text", "Text Message", "Simple text communication"),
                    ActionGroupItem("image", "Image Message", "Send an image with caption"),
                    ActionGroupItem("video", "Video Message", "Send a video with caption"),
                ],
            ),
            ActionGroup(
                title="📎 Documents & Media",
                items=[
                    ActionGroupItem("document", "Document Message", "Send a PDF or file"),
                    ActionGroupItem("audio", "Audio Message", "Send an audio file"),
                    ActionGroupItem("sticker", "Sticker Message", "Send an animated sticker"),
                ],
            ),
            ActionGroup(
                title="🎮 Interactive Messages",
                items=[
                    ActionGroupItem("buttons", "Button Message", "Quick reply buttons"),
                    ActionGroupItem("url", "URL Message", "Call-to-action link"),
                    ActionGroupItem("reaction", "Reaction", "React to a message with emoji"),
                ],
            ),
        ]

        menu = InteractiveListMessage(
            ctx=dc.ctx,
            body="Choose a message type to test:",
            groups=groups,
            button_title="Select Option",
            header="Message Types Demo",
            footer="Reply with your selection",
        )
        await dc.message.send(menu)
        return DialogTurnResult(DialogTurnStatus.Waiting)

    @Dialog.step()
    async def handle_selection(self, dc: DialogContext):
        """Handle user's menu selection and demonstrate the chosen message type."""
        selection = dc.get_value("selected_option")
        logging.info(f"User selected option: {selection}")

        match selection:
            case "text":
                await self.demo_text_message(dc)
            case "image":
                await self.demo_image_message(dc)
            case "video":
                await self.demo_video_message(dc)
            case "document":
                await self.demo_document_message(dc)
            case "audio":
                await self.demo_audio_message(dc)
            case "sticker":
                await self.demo_sticker_message(dc)
            case "buttons":
                await self.demo_button_message(dc)
            case "url":
                await self.demo_url_message(dc)
            case "reaction":
                await self.demo_reaction_message(dc)
            case _:
                message = TextMessage(ctx=dc.ctx, message="❌ Invalid selection. Please try again.")
                await dc.message.send(message)

        await dc.continue_dialog()

    @Dialog.step()
    @Dialog.store("continue_demo")
    async def ask_continue(self, dc: DialogContext):
        """Ask if the user wants to try another message type."""
        buttons = [
            ButtonItem("yes", "Yes, show menu"),
            ButtonItem("no", "No, exit demo"),
        ]

        message = InteractiveButtonMessage(
            ctx=dc.ctx, body="Would you like to try another message type?", buttons=buttons, footer="Choose an option"
        )
        await dc.message.send(message)
        return DialogTurnResult(DialogTurnStatus.Waiting)

    @Dialog.step()
    async def process_continue(self, dc: DialogContext):
        """Process user's decision to continue or exit."""
        user_choice = dc.get_value("continue_demo")

        if user_choice == "yes":
            return await dc.skip_to(self.show_menu)
        else:
            message = TextMessage(ctx=dc.ctx, message="👋 Thanks for trying the Rich Messages Demo! Goodbye!")
            await dc.message.send(message)
            return DialogTurnResult(DialogTurnStatus.Complete)

    # --- Demo Message Methods ---
    async def demo_text_message(self, dc: DialogContext):
        """Demonstrate a simple text message."""
        message = TextMessage(
            ctx=dc.ctx, message="This is a simple text message! You can use emojis, formatting, and more."
        )
        await dc.message.send(message)

    async def demo_image_message(self, dc: DialogContext):
        """Demonstrate an image message with caption."""
        image_url = "https://cdn.ktz.sh/wasup-showcase/image-message.jpg"

        message = ImageMessage(ctx=dc.ctx, media_uri=image_url, caption="🖼️ This is an image message with a caption!")
        await dc.message.send(message)

    async def demo_video_message(self, dc: DialogContext):
        """Demonstrate a video message with caption."""
        video_url = "https://cdn.ktz.sh/wasup-showcase/bad-apple-2mb.mp4"

        message = VideoMessage(ctx=dc.ctx, media_uri=video_url, caption="🎥 This is a video message! Click to play.")
        await dc.message.send(message)

    async def demo_document_message(self, dc: DialogContext):
        """Demonstrate a document message."""
        doc_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"

        message = DocumentMessage(
            ctx=dc.ctx,
            media_uri=doc_url,
            file_name="sample_document.pdf",
            caption="📄 This is a document message with a PDF file.",
        )
        await dc.message.send(message)

    async def demo_audio_message(self, dc: DialogContext):
        """Demonstrate an audio message."""
        audio_url = "https://cdn.ktz.sh/wasup-showcase/un-owen-was-her.mp3"

        message = AudioMessage(ctx=dc.ctx, media_uri=audio_url)
        await dc.message.send(message)

    async def demo_sticker_message(self, dc: DialogContext):
        """Demonstrate a sticker message."""
        # before sending a sticker, it is recommended to check if the format is supported by WhatsApp,
        # alongside the size and dimension requirements. the file's exif data must also be stripped in order to work.
        # for more information, refer to:
        # https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/advanced-messaging/whatsapp/send-sticker-messages?tabs=visual-studio%2Cconnection-string&pivots=programming-language-python
        sticker_url = "https://cdn.ktz.sh/wasup-showcase/sticker.webp"

        message = StickerMessage(ctx=dc.ctx, media_uri=sticker_url)
        await dc.message.send(message)

    async def demo_button_message(self, dc: DialogContext):
        """Demonstrate an interactive button message."""
        buttons = [
            ButtonItem("yes", "Yes ✅"),
            ButtonItem("no", "No ❌"),
            ButtonItem("maybe", "Maybe 🤔"),
        ]

        message = InteractiveButtonMessage(
            ctx=dc.ctx,
            body="Do you like this bot?",
            buttons=buttons,
            header="Quick Question",
            footer="Tap a button to respond",
        )
        await dc.message.send(message)
        return DialogTurnResult(DialogTurnStatus.Waiting)

    async def demo_url_message(self, dc: DialogContext):
        """Demonstrate an interactive URL message."""
        message = InteractiveUrlMessage(
            ctx=dc.ctx,
            body="Check out this cool website!",
            url="https://cdn.ktz.sh/wasup-showcase/index.html",
            title="Learn More Here",
            header="External Link",
            footer="Tap to open in browser",
        )
        await dc.message.send(message)

    async def demo_reaction_message(self, dc: DialogContext):
        """Demonstrate a reaction to a message."""
        reaction = ReactionMessage(ctx=dc.ctx, emoji="👍", message_id=dc.ctx.last_message_id)
        await dc.message.send(reaction)


# Create Bot instance
bot = Bot(port=6969)  # used for local cloudflared tunnel

# Load Dialog into Bot Registry
bot.load_dialog(RichMessagesDialog)

# Initialize Azure client
endpoint = os.getenv("AZURE_COMMUNICATION_ENDPOINT")
notification_client = NotificationMessagesClient.from_connection_string(endpoint)

# Create Azure binding
azure_binding = AzureBindingClient(
    ctx=bot,
    client=notification_client,
    route="/api/whatsapp/events",
)

# Pass Bot to Binding and Run
bot.run(azure_binding)
