import os
import time
from contextlib import asynccontextmanager

import aiohttp
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from loguru import logger

from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper

from app.config import DAILY_API_URL
from app.logging import configure_logging, log_startup_complete, log_shutdown
from app.database import engine
from app.routes import api_router
from app.routes.bot import bot_procs, daily_helpers

_startup_time = time.time()


@asynccontextmanager
async def lifespan(app: FastAPI):
    logger.info("Starting application...")
    aiohttp_session = aiohttp.ClientSession()

    daily_api_key = os.getenv("DAILY_API_KEY", "").strip()
    if not daily_api_key:
        logger.error("No Daily API key found")
        raise Exception("DAILY_API_KEY environment variable is required")

    logger.debug(f"Initializing Daily REST helper with API key: {daily_api_key[:6]}...{daily_api_key[-4:]}")

    daily_helpers["rest"] = DailyRESTHelper(
        daily_api_key=daily_api_key,
        daily_api_url=DAILY_API_URL,
        aiohttp_session=aiohttp_session,
    )

    startup_duration_ms = (time.time() - _startup_time) * 1000
    log_startup_complete(startup_duration_ms)
    yield
    log_shutdown()
    await aiohttp_session.close()
    engine.dispose()
    # Clean up bot processes
    for entry in bot_procs.values():
        proc = entry[0]
        proc.terminate()
        proc.wait()
    logger.info("SERVER_STOPPED: status=graceful")


def create_app() -> FastAPI:
    configure_logging()

    application = FastAPI(lifespan=lifespan)

    application.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    @application.middleware("http")
    async def log_requests(request: Request, call_next):
        start = time.time()
        response = await call_next(request)
        duration = round((time.time() - start) * 1000)
        logger.info(f"{request.method} {request.url.path} -> {response.status_code} ({duration}ms)")
        return response

    application.include_router(api_router)

    return application
