from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
import structlog
import os
from pathlib import Path
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

from .shared.config.loader import load_service_config, get_env_var
from .shared.config.logging_config import setup_logging, get_logger
from .shared.middleware.auth import init_auth_manager
from .shared.middleware.error_handler import service_exception_handler, generic_exception_handler
from .shared.exceptions.base import ServiceException
from .shared.clients.openai_client import openai_client

# Import service configurations
from .services.translation.config import TranslationServiceConfig
from .services.wine_pairing.config import WinePairingServiceConfig
from .services.beer_pairing.config import BeerPairingServiceConfig
from .services.menu_extraction.config import MenuExtractionServiceConfig
from .services.scan_menu.config import InsertMenuItemsServiceConfig
from .services.create_restaurant_offer.config import CreateRestaurantOfferServiceConfig
from .services.generate_ai_image.config import GenerateAiImageServiceConfig

# Import services
from .services.translation.service import TranslationService
from .services.wine_pairing.service import WinePairingService
from .services.beer_pairing.service import BeerPairingService
from .services.menu_extraction.service import MenuExtractionService
from .services.scan_menu.service import InsertMenuItemsService
from .services.create_restaurant_offer.service import CreateRestaurantOfferService
from .services.generate_ai_image.service import GenerateAiImageService
from .shared.services.ai_analytics import AiAnalyticsConfig, AiAnalyticsService

# Import routes
from .services.translation import routes as translation_routes
from .services.wine_pairing import routes as wine_pairing_routes
from .services.beer_pairing import routes as beer_pairing_routes
from .services.menu_extraction import routes as menu_extraction_routes
from .services.scan_menu import routes as insert_menu_items_routes
from .services.create_restaurant_offer import routes as create_restaurant_offer_routes
from .services.generate_ai_image import routes as generate_ai_image_routes
from .services.ai_analytics import routes as ai_analytics_routes
from .services.health import routes as health_routes

# Setup logging
setup_logging()
logger = get_logger("app.main")

# Load configuration
try:
    config = load_service_config()
    logger.info("configuration_loaded", services=list(config["services"].keys()))
except Exception as e:
    logger.error("configuration_load_failed", error=str(e))
    raise

# Initialize authentication
try:
    global_token = get_env_var("AUTHORIZATION_KEY")
    service_tokens = {
        "translation": get_env_var("TRANSLATION_SERVICE_KEY", required=False),
        "wine_pairing": get_env_var("WINE_SERVICE_KEY", required=False),
        "beer_pairing": get_env_var("BEER_SERVICE_KEY", required=False),
        "menu_extraction": get_env_var("MENU_EXTRACTION_SERVICE_KEY", required=False),
        "insert_menu_items": get_env_var("INSERT_MENU_ITEMS_SERVICE_KEY", required=False),
        "create_restaurant_offer": get_env_var("CREATE_RESTAURANT_OFFER_SERVICE_KEY", required=False),
        "generate_ai_image": get_env_var("CREATE_RESTAURANT_OFFER_SERVICE_KEY", required=False),
        "ai_analytics": get_env_var("AI_ANALYTICS_SERVICE_KEY", required=False),
    }
    init_auth_manager(global_token, service_tokens)
    logger.info("authentication_initialized")
except Exception as e:
    logger.error("authentication_init_failed", error=str(e))
    raise

# Initialize services
try:
    # Translation Service
    translation_config = TranslationServiceConfig.from_config(config)
    translation_service = TranslationService(translation_config)
    translation_routes.set_translation_service(translation_service)
    logger.info("translation_service_initialized", model=translation_config.translation_model)

    # Wine Pairing Service
    wine_pairing_config = WinePairingServiceConfig.from_config(config)
    wine_pairing_service = WinePairingService(wine_pairing_config)
    wine_pairing_routes.set_wine_pairing_service(wine_pairing_service)
    logger.info("wine_pairing_service_initialized", model=wine_pairing_config.wine_pairing_model)

    # Beer Pairing Service
    beer_pairing_config = BeerPairingServiceConfig.from_config(config)
    beer_pairing_service = BeerPairingService(beer_pairing_config)
    beer_pairing_routes.set_beer_pairing_service(beer_pairing_service)
    logger.info("beer_pairing_service_initialized", model=beer_pairing_config.beer_pairing_model)

    # Menu Extraction Service
    menu_extraction_config = MenuExtractionServiceConfig.from_config(config)
    menu_extraction_service = MenuExtractionService(menu_extraction_config)
    menu_extraction_routes.set_menu_extraction_service(menu_extraction_service)
    logger.info("menu_extraction_service_initialized", model=menu_extraction_config.menu_extraction_model)

    # Insert Menu Items Service
    insert_menu_items_config = InsertMenuItemsServiceConfig.from_config(config)
    insert_menu_items_service = InsertMenuItemsService(
        config=insert_menu_items_config,
        menu_extraction_service=menu_extraction_service
    )
    insert_menu_items_routes.set_insert_menu_items_service(insert_menu_items_service)
    logger.info("insert_menu_items_service_initialized")

    # Create Restaurant Offer Service
    create_restaurant_offer_config = CreateRestaurantOfferServiceConfig.from_config(config)
    create_restaurant_offer_service = CreateRestaurantOfferService(create_restaurant_offer_config)
    create_restaurant_offer_routes.set_create_restaurant_offer_service(create_restaurant_offer_service)
    logger.info("create_restaurant_offer_service_initialized", model=create_restaurant_offer_config.create_restaurant_offer_model)

    # Generate AI Image Service
    generate_ai_image_config = GenerateAiImageServiceConfig.from_config(config)
    generate_ai_image_service = GenerateAiImageService(generate_ai_image_config)
    generate_ai_image_routes.set_generate_ai_image_service(generate_ai_image_service)
    logger.info("generate_ai_image_service_initialized", model=generate_ai_image_config.generate_ai_image_model)

    # AI Analytics Service
    ai_analytics_config = AiAnalyticsConfig.from_env()
    ai_analytics_service = AiAnalyticsService(ai_analytics_config)
    openai_client.set_analytics_service(ai_analytics_service)
    ai_analytics_routes.set_ai_analytics_service(ai_analytics_service)
    logger.info("ai_analytics_service_initialized", url=ai_analytics_config.url)

except Exception as e:
    logger.error("service_initialization_failed", error=str(e))
    raise

# Create FastAPI app
app = FastAPI(
    title="AI Menu Translator",
    version="2.0.0",
    description="Scalable service-oriented menu translation API"
)

# Serve generated menu images from /menues/{zId}/{file}
menues_dir = Path("menues")
menues_dir.mkdir(parents=True, exist_ok=True)
app.mount("/menues", StaticFiles(directory=str(menues_dir)), name="menues")

# Serve observability upload copies from /observability/{request_id}/{file}
observability_dir = Path("observability")
observability_dir.mkdir(parents=True, exist_ok=True)
app.mount("/observability", StaticFiles(directory=str(observability_dir)), name="observability")

# Add exception handlers
app.add_exception_handler(ServiceException, service_exception_handler)
app.add_exception_handler(Exception, generic_exception_handler)

# Include routers
app.include_router(translation_routes.router)
app.include_router(wine_pairing_routes.router)
app.include_router(beer_pairing_routes.router)
app.include_router(menu_extraction_routes.router)
app.include_router(insert_menu_items_routes.router)
app.include_router(create_restaurant_offer_routes.router)
app.include_router(generate_ai_image_routes.router)
app.include_router(ai_analytics_routes.router)
app.include_router(health_routes.router)


@app.on_event("startup")
async def startup_event():
    logger.info(
        "application_startup",
        version="2.0.0",
        services=["translation", "wine_pairing", "beer_pairing", "menu_extraction", "insert_menu_items", "create_restaurant_offer", "generate_ai_image"],
        translation_model=translation_config.translation_model,
        wine_pairing_model=wine_pairing_config.wine_pairing_model,
        beer_pairing_model=beer_pairing_config.beer_pairing_model,
        menu_extraction_model=menu_extraction_config.menu_extraction_model,
        create_restaurant_offer_model=create_restaurant_offer_config.create_restaurant_offer_model,
        generate_ai_image_model=generate_ai_image_config.generate_ai_image_model,
    )


@app.on_event("shutdown")
async def shutdown_event():
    logger.info("application_shutdown")
    try:
        await openai_client.close()
        logger.info("openai_client_closed")
    except Exception as e:
        logger.error("openai_client_close_error", error=str(e))
