"""Environment configuration utilities.

This module provides utilities for loading environment variables from .env files.
It's designed to work seamlessly whether fluxibly is used as a development
project or installed as a pip package.

Usage:
    # Option 1: Auto-discover .env file in current working directory
    from fluxibly.config import load_env
    load_env()

    # Option 2: Specify a custom env file path
    from fluxibly.config import load_env
    load_env("/path/to/my/.env")

    # Option 3: Just set environment variables directly (no .env file needed)
    import os
    os.environ["OPENAI_API_KEY"] = "sk-..."
"""

import os
from pathlib import Path

import loguru
from dotenv import load_dotenv

logger = loguru.logger.bind(name=__name__)


def load_env(
    env_file: str | Path | None = None,
    *,
    override: bool = False,
    verbose: bool = False,
) -> bool:
    """Load environment variables from a .env file.

    This function provides flexible environment loading that works for both
    development and production use cases:

    1. If env_file is provided, load from that specific path
    2. Otherwise, search for .env file in current working directory
    3. If no .env file is found, silently continue (env vars may be set directly)

    Args:
        env_file: Optional path to .env file. If None, searches current directory.
        override: If True, override existing environment variables. Default False.
        verbose: If True, log which file was loaded. Default False.

    Returns:
        True if an env file was found and loaded, False otherwise.

    Example:
        >>> from fluxibly.config import load_env
        >>>
        >>> # Auto-discover .env in current directory
        >>> load_env()
        >>>
        >>> # Load from specific file
        >>> load_env("/path/to/my/config.env")
        >>>
        >>> # Override existing env vars
        >>> load_env(override=True)
    """
    # If explicit path provided, use it directly
    if env_file is not None:
        env_path = Path(env_file)
        if env_path.exists():
            load_dotenv(env_path, override=override)
            if verbose:
                logger.info("Loaded environment from file", path=str(env_path))
            return True
        else:
            logger.warning("Specified env file not found", path=str(env_path))
            return False

    # Auto-discover .env file
    search_paths = [
        Path.cwd() / ".env",  # Current working directory
        Path.cwd() / ".env.local",  # Local override file
    ]

    for path in search_paths:
        if path.exists():
            load_dotenv(path, override=override)
            if verbose:
                logger.info("Loaded environment from file", path=str(path))
            return True

    # No .env file found - this is fine, env vars may be set directly
    if verbose:
        logger.debug("No .env file found, using existing environment variables")
    return False


def get_api_key(provider: str | None = None) -> str | None:
    """Get API key for the specified provider from environment.

    This is a convenience function to retrieve API keys following
    the standard naming convention.

    Args:
        provider: Provider name (openai, anthropic, google). If None, tries each.

    Returns:
        API key string if found, None otherwise.

    Example:
        >>> from fluxibly.config import get_api_key
        >>>
        >>> # Get OpenAI key
        >>> key = get_api_key("openai")
        >>>
        >>> # Get any available key
        >>> key = get_api_key()
    """
    key_mapping = {
        "openai": "OPENAI_API_KEY",
        "anthropic": "ANTHROPIC_API_KEY",
        "google": "GOOGLE_API_KEY",
        "gemini": "GOOGLE_API_KEY",
    }

    if provider is not None:
        env_var = key_mapping.get(provider.lower())
        if env_var:
            return os.getenv(env_var)
        return None

    # Try all providers in order
    for env_var in ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GOOGLE_API_KEY"]:
        key = os.getenv(env_var)
        if key:
            return key

    return None


def require_api_key(provider: str | None = None) -> str:
    """Get API key or raise an error if not found.

    Args:
        provider: Provider name (openai, anthropic, google). If None, tries each.

    Returns:
        API key string.

    Raises:
        EnvironmentError: If no API key is found.

    Example:
        >>> from fluxibly.config import require_api_key
        >>>
        >>> # Will raise if OPENAI_API_KEY not set
        >>> key = require_api_key("openai")
    """
    key = get_api_key(provider)
    if key is None:
        if provider:
            env_var = {
                "openai": "OPENAI_API_KEY",
                "anthropic": "ANTHROPIC_API_KEY",
                "google": "GOOGLE_API_KEY",
            }.get(provider.lower(), f"{provider.upper()}_API_KEY")
            raise OSError(
                f"API key not found. Please set the {env_var} environment variable "
                f"or create a .env file in your project directory."
            )
        raise OSError(
            "No API key found. Please set OPENAI_API_KEY, ANTHROPIC_API_KEY, "
            "or GOOGLE_API_KEY environment variable, or create a .env file."
        )
    return key


def configure_langsmith(
    api_key: str | None = None,
    project: str | None = None,
    *,
    endpoint: str | None = None,
    enabled: bool = True,
) -> bool:
    """Configure LangSmith tracing for LangChain operations.

    This function sets up the environment variables required for LangSmith
    tracing. Call this at the start of your application to enable observability
    for all LangChain/LangGraph operations.

    Args:
        api_key: LangSmith API key. If None, uses LANGCHAIN_API_KEY from environment.
        project: LangSmith project name. If None, uses LANGCHAIN_PROJECT from environment
            or defaults to "default".
        endpoint: Custom LangSmith endpoint URL. If None, uses the default LangSmith endpoint.
        enabled: Whether to enable tracing. Set to False to disable. Default True.

    Returns:
        True if LangSmith was configured successfully, False if API key is missing.

    Example:
        >>> from fluxibly.config import configure_langsmith
        >>>
        >>> # Configure with explicit API key and project
        >>> configure_langsmith(
        ...     api_key="lsv2_pt_xxxxx",
        ...     project="my-fluxibly-project"
        ... )
        >>>
        >>> # Configure using environment variables (just enable tracing)
        >>> configure_langsmith()
        >>>
        >>> # Disable tracing
        >>> configure_langsmith(enabled=False)
    """
    if not enabled:
        os.environ["LANGCHAIN_TRACING_V2"] = "false"
        logger.debug("LangSmith tracing disabled")
        return True

    # Get API key from parameter or environment
    resolved_api_key = api_key or os.getenv("LANGCHAIN_API_KEY")
    if not resolved_api_key:
        logger.warning(
            "LangSmith API key not provided. Set LANGCHAIN_API_KEY environment variable "
            "or pass api_key parameter to enable tracing."
        )
        return False

    # Set required environment variables
    os.environ["LANGCHAIN_TRACING_V2"] = "true"
    os.environ["LANGCHAIN_API_KEY"] = resolved_api_key

    # Set optional project name
    if project:
        os.environ["LANGCHAIN_PROJECT"] = project
    elif not os.getenv("LANGCHAIN_PROJECT"):
        os.environ["LANGCHAIN_PROJECT"] = "default"

    # Set custom endpoint if provided
    if endpoint:
        os.environ["LANGCHAIN_ENDPOINT"] = endpoint

    logger.info(
        "LangSmith tracing configured",
        project=os.environ.get("LANGCHAIN_PROJECT"),
        endpoint=endpoint or "https://api.smith.langchain.com",
    )
    return True


def is_langsmith_enabled() -> bool:
    """Check if LangSmith tracing is currently enabled.

    Returns:
        True if tracing is enabled and API key is set, False otherwise.

    Example:
        >>> from fluxibly.config import is_langsmith_enabled
        >>>
        >>> if is_langsmith_enabled():
        ...     print("LangSmith tracing is active")
    """
    tracing_enabled = os.getenv("LANGCHAIN_TRACING_V2", "").lower() == "true"
    has_api_key = bool(os.getenv("LANGCHAIN_API_KEY"))
    return tracing_enabled and has_api_key
