"""OpenAI LLM provider for Local Deep Research."""

from langchain_openai import ChatOpenAI
from loguru import logger

from ....config.thread_settings import (
    get_setting_from_snapshot as _get_setting_from_snapshot,
    NoSettingsContextError,
)
from ...llm_registry import register_llm
from ..openai_base import OpenAICompatibleProvider


def get_setting_from_snapshot(
    key, default=None, username=None, settings_snapshot=None
):
    """Get setting from context only - no database access from threads.

    This is a wrapper around the shared function that enables fallback LLM check.
    """
    return _get_setting_from_snapshot(
        key, default, username, settings_snapshot, check_fallback_llm=True
    )


class OpenAIProvider(OpenAICompatibleProvider):
    """OpenAI provider for Local Deep Research.

    This is the official OpenAI API provider.
    """

    provider_name = "OpenAI"
    api_key_setting = "llm.openai.api_key"
    default_model = "gpt-3.5-turbo"
    default_base_url = "https://api.openai.com/v1"

    # Metadata for auto-discovery
    provider_key = "OPENAI"
    company_name = "OpenAI"
    region = "US"
    country = "United States"
    data_location = "United States"
    is_cloud = True

    @classmethod
    def create_llm(cls, model_name=None, temperature=0.7, **kwargs):
        """Factory function for OpenAI LLMs.

        Args:
            model_name: Name of the model to use
            temperature: Model temperature (0.0-1.0)
            **kwargs: Additional arguments including settings_snapshot

        Returns:
            A configured ChatOpenAI instance

        Raises:
            ValueError: If API key is not configured
        """
        settings_snapshot = kwargs.get("settings_snapshot")

        # Get API key from settings
        api_key = get_setting_from_snapshot(
            cls.api_key_setting,
            default=None,
            settings_snapshot=settings_snapshot,
        )

        if not api_key:
            logger.error(f"{cls.provider_name} API key not found in settings")
            raise ValueError(
                f"{cls.provider_name} API key not configured. "
                f"Please set {cls.api_key_setting} in settings."
            )

        # Use default model if none specified
        if not model_name:
            model_name = cls.default_model

        # Build OpenAI-specific parameters
        openai_params = {
            "model": model_name,
            "api_key": api_key,
            "temperature": temperature,
        }

        # Add optional parameters if they exist in settings
        try:
            api_base = get_setting_from_snapshot(
                "llm.openai.api_base",
                default=None,
                settings_snapshot=settings_snapshot,
            )
            if api_base:
                openai_params["openai_api_base"] = api_base
        except NoSettingsContextError:
            pass  # Optional parameter

        try:
            organization = get_setting_from_snapshot(
                "llm.openai.organization",
                default=None,
                settings_snapshot=settings_snapshot,
            )
            if organization:
                openai_params["openai_organization"] = organization
        except NoSettingsContextError:
            pass  # Optional parameter

        try:
            streaming = get_setting_from_snapshot(
                "llm.streaming",
                default=None,
                settings_snapshot=settings_snapshot,
            )
            if streaming is not None:
                openai_params["streaming"] = streaming
        except NoSettingsContextError:
            pass  # Optional parameter

        try:
            max_retries = get_setting_from_snapshot(
                "llm.max_retries",
                default=None,
                settings_snapshot=settings_snapshot,
            )
            if max_retries is not None:
                openai_params["max_retries"] = max_retries
        except NoSettingsContextError:
            pass  # Optional parameter

        try:
            request_timeout = get_setting_from_snapshot(
                "llm.request_timeout",
                default=None,
                settings_snapshot=settings_snapshot,
            )
            if request_timeout is not None:
                openai_params["request_timeout"] = request_timeout
        except NoSettingsContextError:
            pass  # Optional parameter

        # Add max_tokens if specified in settings
        try:
            max_tokens = get_setting_from_snapshot(
                "llm.max_tokens",
                default=None,
                settings_snapshot=settings_snapshot,
            )
            if max_tokens:
                openai_params["max_tokens"] = int(max_tokens)
        except NoSettingsContextError:
            pass  # Optional parameter

        logger.info(
            f"Creating {cls.provider_name} LLM with model: {model_name}, "
            f"temperature: {temperature}"
        )

        return ChatOpenAI(**openai_params)

    @classmethod
    def is_available(cls, settings_snapshot=None):
        """Check if this provider is available.

        Args:
            settings_snapshot: Optional settings snapshot to use

        Returns:
            True if API key is configured, False otherwise
        """
        try:
            # Check if API key is configured
            api_key = get_setting_from_snapshot(
                cls.api_key_setting,
                default=None,
                settings_snapshot=settings_snapshot,
            )
            return bool(api_key)
        except Exception:
            return False


# Keep the standalone functions for backward compatibility and registration
def create_openai_llm(model_name=None, temperature=0.7, **kwargs):
    """Factory function for OpenAI LLMs.

    Args:
        model_name: Name of the model to use (e.g., "gpt-4", "gpt-3.5-turbo", etc.)
        temperature: Model temperature (0.0-1.0)
        **kwargs: Additional arguments including settings_snapshot

    Returns:
        A configured ChatOpenAI instance

    Raises:
        ValueError: If OpenAI API key is not configured
    """
    return OpenAIProvider.create_llm(model_name, temperature, **kwargs)


def is_openai_available(settings_snapshot=None):
    """Check if OpenAI is available.

    Args:
        settings_snapshot: Optional settings snapshot to use

    Returns:
        True if OpenAI API key is configured, False otherwise
    """
    return OpenAIProvider.is_available(settings_snapshot)


def register_openai_provider():
    """Register the OpenAI provider with the LLM registry."""
    register_llm("openai", create_openai_llm)
    logger.info("Registered OpenAI LLM provider")
