# app/app.py
from fastapi import FastAPI
from contextlib import asynccontextmanager
from typing import List

# Import centralized settings and other components
from app.config import settings
from app.core.vector_store.faiss_store import FaissVectorStore
from app.core.vector_store.embedder.factory import get_embedder_from_config
from app.core.providers.factory import get_tts_provider, get_stt_provider
from app.core.retrievers.faiss_db_retriever import FaissDBRetriever
from app.core.retrievers.base_retriever import Retriever
from app.db.session import create_db_and_tables
from app.api.routes.api import create_api_router
from app.utils import print_config 
from app.api.dependencies import ServiceContainer
from app.core.services.tts import TTSService
from app.core.services.stt import STTService # NEW: Added the missing import for STTService
# Note: The llm_clients import and initialization are removed as they
# are not used in RAGService's constructor based on your services.py
# from app.core.llm_clients import DeepSeekClient, GeminiClient

@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    Manages application startup and shutdown events.
    - On startup, it creates database tables.
    - On shutdown, it saves the FAISS index to disk.
    """
    print("Application startup...")
    print_config(settings)
    create_db_and_tables()
    yield
    print("Application shutdown...")
    # Access the vector_store from the application state to save it
    if hasattr(app.state, 'vector_store'):
        app.state.vector_store.save_index()

def create_app() -> FastAPI:
    """
    Factory function to create and configure the FastAPI application.
    This encapsulates all setup logic, making the main entry point clean.
    """
    app = FastAPI(
        # Use metadata from the central settings
        title=settings.PROJECT_NAME,
        version=settings.VERSION,
        description="A modular API to route requests to various LLMs with RAG capabilities.",
        lifespan=lifespan
    )

    # --- Initialize Core Services using settings ---
    
    # 1. Use the new, more flexible factory function to create the embedder instance
    # This decouples the application from a specific embedding provider.
    embedder = get_embedder_from_config(
        provider=settings.EMBEDDING_PROVIDER,
        dimension=settings.EMBEDDING_DIMENSION,
        model_name=settings.EMBEDDING_MODEL_NAME,
        api_key=settings.EMBEDDING_API_KEY
    )
        
    # 2. Initialize the FaissVectorStore with the chosen embedder
    vector_store = FaissVectorStore(
        index_file_path=settings.FAISS_INDEX_PATH,
        dimension=settings.EMBEDDING_DIMENSION,
        embedder=embedder # Pass the instantiated embedder object,
        
    )
    
    # CRITICAL FIX: Assign the vector_store to the app state so it can be saved on shutdown.
    app.state.vector_store = vector_store
    
    # 3. Create the FaissDBRetriever, regardless of the embedder type
    retrievers: List[Retriever] = [
        FaissDBRetriever(vector_store=vector_store),
    ]
    
    # --- New TTS Initialization ---
    # 4. Get the concrete TTS provider from the factory
    tts_provider = get_tts_provider(
        provider_name=settings.TTS_PROVIDER,
        api_key=settings.TTS_API_KEY,
        voice_name=settings.TTS_VOICE_NAME
    )
    
    # 5. Initialize the TTSService
    tts_service = TTSService(tts_provider=tts_provider)

    # 6. Get the concrete STT provider from the factory
    stt_provider = get_stt_provider(
        provider_name=settings.STT_PROVIDER,
        api_key=settings.STT_API_KEY,
        model_name=settings.STT_MODEL_NAME
    )
    # 7. Initialize the STTService
    stt_service = STTService(stt_provider=stt_provider)
    
    # 8. Initialize the Service Container with all services
    # This replaces the previous, redundant initialization
    services = ServiceContainer(
        vector_store=vector_store,
        retrievers=retrievers,
        tts_service=tts_service,
        stt_service=stt_service # NEW: Pass the new STT service instance
    )

    # Create and include the API router, injecting the service
    api_router = create_api_router(services=services)
    app.include_router(api_router)

    return app
