"""Restaurant booking bot - example bot for simulation testing.

This module contains a simple restaurant booking assistant bot.
It can be used standalone or with Voiceground's simulation feature.

The bot can:
- Make reservations (date, time, party size, name)
- Answer questions about the menu (Italian cuisine)
- Provide restaurant hours (open 11am-10pm daily)
"""

import os
import uuid

import aiohttp
from loguru import logger
from pipecat.frames.frames import CancelFrame
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineTask
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair
from pipecat.services.elevenlabs.stt import ElevenLabsSTTService
from pipecat.services.elevenlabs.tts import ElevenLabsTTSService
from pipecat.services.openai.llm import OpenAILLMService
from pipecat.transports.base_transport import BaseTransport

from voiceground import HTMLReporter, VoicegroundObserver

# Bot system prompt
SYSTEM_PROMPT = """You are a helpful restaurant booking assistant for "The Golden Fork" restaurant.

You can help customers:
- Make reservations (ask for date, time, party size, name)
- Answer questions about the menu (Italian cuisine)
- Provide restaurant hours (open 11am-10pm daily)

Be friendly, professional, and concise. Confirm reservation details before finalizing."""


async def run_restaurant_bot(transport: BaseTransport) -> None:
    """Run the restaurant booking bot.

    This bot works with any Pipecat transport - LocalAudioTransport for
    production, WebsocketTransport for web apps, or VoicegroundBridgeTransport
    for simulation testing.

    The bot manages its own services internally. Just pass the transport.

    Args:
        transport: The Pipecat transport to use (any BaseTransport).
    """
    # Load API keys from environment
    openai_key = os.environ["OPENAI_API_KEY"]
    elevenlabs_key = os.environ["ELEVENLABS_API_KEY"]
    voice_id = os.environ["VOICE_ID"]

    conversation_id = str(uuid.uuid4())

    async with aiohttp.ClientSession() as session:
        # Initialize services
        stt = ElevenLabsSTTService(
            api_key=elevenlabs_key,
            aiohttp_session=session,
        )

        tts = ElevenLabsTTSService(
            api_key=elevenlabs_key,
            aiohttp_session=session,
            voice_id=voice_id,
        )

        llm = OpenAILLMService(
            api_key=openai_key,
            model="gpt-4o-mini",
        )

        # Set up conversation context
        messages = [{"role": "system", "content": SYSTEM_PROMPT}]
        context = LLMContext(messages)
        context_aggregator = LLMContextAggregatorPair(context)

        # Build pipeline
        pipeline = Pipeline(
            [
                transport.input(),
                stt,
                context_aggregator.user(),
                llm,
                tts,
                transport.output(),
                context_aggregator.assistant(),
            ]
        )

        # Set up Voiceground observer with HTML reporter
        reporter = HTMLReporter(output_dir="./reports", auto_open=True)
        observer = VoicegroundObserver(
            reporters=[reporter],
            conversation_id=conversation_id,
        )

        # Create task
        task = PipelineTask(
            pipeline,
            observers=[observer],
            conversation_id=conversation_id,
        )

        # Handle client disconnect (important for simulation)
        @transport.event_handler("on_client_disconnected")
        async def on_client_disconnected(transport, *args, **kwargs):
            logger.info("Client disconnected, stopping bot")
            await task.queue_frame(CancelFrame())

        runner = PipelineRunner()
        await runner.run(task)
