import logging
import os
import sys
from pathlib import Path

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

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 ButtonItem, InteractiveButtonMessage, TextMessage
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="AcceptMediaDialog", main=True)
class AcceptMediaDialog(Dialog):
    """
    Demonstrates the @Dialog.accept_media decorator.

    Some steps in this dialog only activate when the user sends a specific
    media type. Steps without the decorator only activate for text messages.
    """

    @Dialog.step()
    async def welcome(self, dc: DialogContext):
        """Greet the user and explain the demo."""
        message = TextMessage(
            ctx=dc.ctx,
            message=(
                "Welcome to the media upload demo!\n\n"
                "Send me an image or document and I'll acknowledge it. "
                "Text messages will prompt you to send a file instead."
            ),
        )
        await dc.message.send(message)
        return DialogTurnResult(DialogTurnStatus.Waiting)

    @Dialog.step()
    @Dialog.accept_media("image", "document", prompt="Please send an image or document.")
    async def receive_file(self, dc: DialogContext):
        """Accept only image or document uploads."""
        message = TextMessage(ctx=dc.ctx, message="Got your file! Thanks for sending it.")

        # download image
        await dc.ctx.client.download_media(media=dc.ctx.incoming_media, path=Path("."))

        await dc.message.send(message)
        await dc.continue_dialog()

    @Dialog.step()
    @Dialog.store("user_choice")
    async def ask_continue(self, dc: DialogContext):
        """Ask the user whether to upload another file or finish."""
        buttons = [
            ButtonItem("another", "Upload another"),
            ButtonItem("done", "I'm done"),
        ]
        message = InteractiveButtonMessage(
            ctx=dc.ctx,
            body="Would you like to send another file?",
            buttons=buttons,
        )
        await dc.message.send(message)
        return DialogTurnResult(DialogTurnStatus.Waiting)

    @Dialog.step()
    async def process_choice(self, dc: DialogContext):
        """Loop back or finish based on the user's choice."""
        choice = dc.get_value("user_choice")

        if choice == "another":
            return await dc.skip_to(self.receive_file)

        message = TextMessage(ctx=dc.ctx, message="All done! Thanks for trying the media upload demo.")
        await dc.message.send(message)
        return DialogTurnResult(DialogTurnStatus.Complete)


# create Bot instance
bot = Bot(port=6969)

# load Dialog into Bot Registry
bot.load_dialog(AcceptMediaDialog)

# 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)
