from app.core.config import settings
from langchain_openai import OpenAIEmbeddings
from langchain_ollama import OllamaEmbeddings
from typing import Optional
# If you plan on adding other embeddings, import them here
# from some_other_module import AnotherEmbeddingClass


class EmbeddingsFactory:
    @staticmethod
    def create(provider: Optional[str] = None, model_profile: Optional[object] = None):
        """
        Factory method to create an embeddings instance based on .env config.
        """
        if model_profile is not None:
            embeddings_provider = (provider or getattr(model_profile, "provider", None) or "dashscope").lower()
            api_key = getattr(model_profile, "api_key", "") or ""
            api_base = getattr(model_profile, "api_base", None) or _default_api_base(embeddings_provider)
            model = getattr(model_profile, "embedding_model", None) or _default_embedding_model(embeddings_provider)
        else:
            embeddings_provider = (provider or settings.EMBEDDINGS_PROVIDER).lower()
            api_key = _default_api_key(embeddings_provider)
            api_base = _default_api_base(embeddings_provider)
            model = _default_embedding_model(embeddings_provider)

        if embeddings_provider == "openai":
            return OpenAIEmbeddings(
                openai_api_key=api_key,
                openai_api_base=api_base,
                model=model
            )
        elif embeddings_provider in {"dashscope", "openai_compatible"}:
            return OpenAIEmbeddings(
                openai_api_key=api_key,
                openai_api_base=api_base,
                model=model,
                # DashScope OpenAI-compatible embedding expects string input,
                # while LangChain's len-safe path may send token ids.
                check_embedding_ctx_length=False,
                tiktoken_enabled=False,
                skip_empty=True,
                # DashScope embedding API supports at most 10 inputs per batch.
                chunk_size=10,
            )
        elif embeddings_provider == "ollama":
            return OllamaEmbeddings(
                model=model,
                base_url=api_base
            )

        # Extend with other providers:
        # elif embeddings_provider == "another_provider":
        #     return AnotherEmbeddingClass(...)
        else:
            raise ValueError(f"Unsupported embeddings provider: {embeddings_provider}")


def _default_embedding_model(provider: Optional[str]) -> str:
    provider = (provider or settings.EMBEDDINGS_PROVIDER).lower()
    if provider == "openai":
        return settings.OPENAI_EMBEDDINGS_MODEL
    if provider == "dashscope":
        return settings.DASH_SCOPE_EMBEDDINGS_MODEL or "text-embedding-v4"
    if provider == "ollama":
        return settings.OLLAMA_EMBEDDINGS_MODEL
    return settings.DASH_SCOPE_EMBEDDINGS_MODEL or settings.OPENAI_EMBEDDINGS_MODEL


def _default_api_key(provider: Optional[str]) -> str:
    provider = (provider or settings.EMBEDDINGS_PROVIDER).lower()
    if provider == "openai":
        return settings.OPENAI_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.EMBEDDINGS_PROVIDER).lower()
    if provider == "openai":
        return settings.OPENAI_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
