import logging
from collections.abc import AsyncGenerator
from functools import lru_cache

from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine

from app.config import settings

logger = logging.getLogger(__name__)

engine = create_async_engine(settings.DATABASE_URL, echo=False)
async_session_factory = async_sessionmaker(engine, expire_on_commit=False)


async def get_db() -> AsyncGenerator[AsyncSession, None]:
    async with async_session_factory() as session:
        yield session


@lru_cache(maxsize=1)
def get_face_analyzer():
    """Singleton FaceAnalyzer instance (heavy model load, cached)."""
    from app.utils.face_analyzer import FaceAnalyzer

    logger.info("Loading FaceAnalyzer model (first call)...")
    return FaceAnalyzer()


def get_face_service():
    """Create FaceService with the singleton analyzer."""
    from app.services.face_service import FaceService

    return FaceService(analyzer=get_face_analyzer())


@lru_cache(maxsize=1)
def get_llm_provider():
    """Singleton LLM provider based on LLM_PROVIDER env var."""
    provider_name = settings.LLM_PROVIDER.lower()
    if provider_name == "openai":
        from app.services.llm.openai import OpenAIProvider
        logger.info("Using OpenAI LLM provider")
        return OpenAIProvider()
    else:
        from app.services.llm.gemini import GeminiProvider
        logger.info("Using Gemini LLM provider")
        return GeminiProvider()


def get_garment_service():
    """Create GarmentService with the singleton LLM provider + segmentation."""
    from app.services.garment_service import GarmentService

    return GarmentService(
        llm_provider=get_llm_provider(),
        segmentation_service=get_segmentation_service(),
    )


def get_wardrobe_service():
    """Create WardrobeService."""
    from app.services.wardrobe_service import WardrobeService

    return WardrobeService()


def get_vton_service():
    """Create VtonService with the singleton LLM provider + face analyzer + segmentation."""
    from app.services.vton_service import VtonService

    return VtonService(
        llm_provider=get_llm_provider(),
        face_analyzer=get_face_analyzer(),
        segmentation_service=get_segmentation_service(),
    )


@lru_cache(maxsize=1)
def get_segmentation_service():
    """Singleton SegmentationService (heavy model load, cached)."""
    from app.services.segmentation_service import SegmentationService

    logger.info("Loading SegmentationService model (first call)...")
    return SegmentationService()
