from typing import Optional
from langchain_core.language_models import BaseChatModel
from langchain_openai import ChatOpenAI
from langchain_deepseek import ChatDeepSeek
from langchain_ollama import OllamaLLM
from app.core.config import settings

class LLMFactory:
    @staticmethod
    def create(
        provider: Optional[str] = None,
        temperature: float = 0,
        streaming: bool = True,
        model_profile: Optional[object] = None,
    ) -> BaseChatModel:
        """
        Create a LLM instance based on the provider
        """
        if model_profile is not None:
            provider = (provider or getattr(model_profile, "provider", None) or "dashscope").lower()
            model = getattr(model_profile, "chat_model", None) or _default_chat_model(provider)
            api_key = getattr(model_profile, "api_key", "") or ""
            api_base = getattr(model_profile, "api_base", None) or _default_api_base(provider)
        else:
            provider = provider or settings.CHAT_PROVIDER
            model = _default_chat_model(provider)
            api_key = _default_api_key(provider)
            api_base = _default_api_base(provider)

        if provider.lower() == "openai":
            return ChatOpenAI(
                temperature=temperature,
                streaming=streaming,
                model=model,
                openai_api_key=api_key,
                openai_api_base=api_base
            )
        elif provider.lower() == "deepseek":
            return ChatDeepSeek(
                temperature=temperature,
                streaming=streaming,
                model=model,
                api_key=api_key,
                api_base=api_base
            )
        elif provider.lower() in {"dashscope", "openai_compatible"}:
            return ChatOpenAI(
                temperature=temperature,
                streaming=streaming,
                model=model,
                openai_api_key=api_key,
                openai_api_base=api_base,
            )
        elif provider.lower() == "ollama":
            # Initialize Ollama model
            return OllamaLLM(
                model=model,
                base_url=api_base,
                temperature=temperature,
                streaming=streaming
            )
        # Add more providers here as needed
        # elif provider.lower() == "anthropic":
        #     return ChatAnthropic(...)
        else:
            raise ValueError(f"Unsupported LLM provider: {provider}")


def _default_chat_model(provider: Optional[str]) -> str:
    provider = (provider or settings.CHAT_PROVIDER).lower()
    if provider == "openai":
        return settings.OPENAI_MODEL
    if provider == "deepseek":
        return settings.DEEPSEEK_MODEL
    if provider == "dashscope":
        return settings.DASH_SCOPE_CHAT_MODEL
    if provider == "ollama":
        return settings.OLLAMA_MODEL
    return settings.DASH_SCOPE_CHAT_MODEL or settings.OPENAI_MODEL


def _default_api_key(provider: Optional[str]) -> str:
    provider = (provider or settings.CHAT_PROVIDER).lower()
    if provider == "openai":
        return settings.OPENAI_API_KEY
    if provider == "deepseek":
        return settings.DEEPSEEK_API_KEY
    if provider == "dashscope":
        return settings.DASH_SCOPE_API_KEY
    return settings.API_KEY


def _default_api_base(provider: Optional[str]) -> str:
    provider = (provider or settings.CHAT_PROVIDER).lower()
    if provider == "openai":
        return settings.OPENAI_API_BASE
    if provider == "deepseek":
        return settings.DEEPSEEK_API_BASE
    if provider == "dashscope":
        return settings.DASH_SCOPE_API_BASE
    if provider == "ollama":
        return settings.OLLAMA_API_BASE
    return settings.DASH_SCOPE_API_BASE
