"""
Configuration system for global and per-agent settings.

This module provides configuration classes for GSD-RLM:
- LLMConfig: LLM provider configuration with support for 75+ providers
- GSDConfig: Global configuration with environment variable support

Requirements: INT-06 (multi-provider support), INT-07 (local-first defaults)
"""

from __future__ import annotations

import os
from pathlib import Path
from typing import Any, Dict, Optional

from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings

from gsd_rlm.agents.definition import LLMProvider


class LLMConfig(BaseModel):
    """LLM provider configuration (INT-06, INT-07).

    Supports configuration for multiple LLM providers including:
    - Ollama (default, local-first)
    - OpenAI
    - Anthropic
    - Google/Gemini
    - Custom providers via base_url

    Example:
        ```python
        # Ollama (local)
        config = LLMConfig(provider=LLMProvider.OLLAMA, model="llama3.2")

        # OpenAI
        config = LLMConfig(
            provider=LLMProvider.OPENAI,
            model="gpt-4",
            api_key="sk-..."
        )
        ```
    """

    provider: LLMProvider = LLMProvider.OLLAMA
    model: str = "llama3.2"
    api_key: Optional[str] = None
    base_url: Optional[str] = None
    temperature: float = Field(default=0.7, ge=0.0, le=2.0)
    max_tokens: int = Field(default=4096, ge=1)

    def get_provider_instance(self):
        """Create LLM provider instance.

        Returns an LLM provider instance configured with the settings.
        Requires rlm_toolkit to be installed for actual provider creation.

        Returns:
            LLM provider instance

        Raises:
            ImportError: If rlm_toolkit is not installed
            ValueError: If provider type is unknown
        """
        try:
            from rlm_toolkit.providers import (
                OllamaProvider,
                OpenAIProvider,
                AnthropicProvider,
                GeminiProvider,
            )
        except ImportError:
            raise ImportError(
                "rlm_toolkit is required for LLM provider instances. "
                "Install with: pip install rlm-toolkit"
            )

        if self.provider == LLMProvider.OLLAMA:
            return OllamaProvider(
                model=self.model,
                base_url=self.base_url or "http://localhost:11434",
            )
        elif self.provider == LLMProvider.OPENAI:
            return OpenAIProvider(
                model=self.model,
                api_key=self.api_key or os.getenv("OPENAI_API_KEY"),
            )
        elif self.provider == LLMProvider.ANTHROPIC:
            return AnthropicProvider(
                model=self.model,
                api_key=self.api_key or os.getenv("ANTHROPIC_API_KEY"),
            )
        elif self.provider == LLMProvider.GOOGLE:
            return GeminiProvider(
                model=self.model,
                api_key=self.api_key or os.getenv("GOOGLE_API_KEY"),
            )
        else:
            raise ValueError(f"Unknown provider: {self.provider}")


class GSDConfig(BaseSettings):
    """Global GSD-RLM configuration.

    Configuration can be provided via:
    - Environment variables (with GSD_ prefix)
    - .env file
    - Configuration file (YAML/JSON)
    - Direct instantiation

    Environment Variables:
        GSD_PROJECT_DIR: Project directory path
        GSD_AGENTS_DIR: Directory containing agent YAML files
        GSD_SESSIONS_DIR: Directory for session storage
        GSD_DEFAULT_TIMEOUT: Default timeout in seconds
        GSD_MAX_RETRIES: Maximum retry attempts

    Example:
        ```python
        # From environment
        config = GSDConfig()

        # From file
        config = GSDConfig.load(Path("gsd-config.yaml"))

        # Direct
        config = GSDConfig(
            project_dir=Path("/my/project"),
            default_timeout=300
        )
        ```
    """

    model_config = {"env_prefix": "GSD_", "env_file": ".env", "extra": "ignore"}

    # Project settings
    project_dir: Path = Field(default_factory=lambda: Path.cwd())
    agents_dir: Path = Field(default=Path("agents"))
    sessions_dir: Path = Field(default=Path(".gsd-sessions"))

    # Default LLM configuration
    default_llm: LLMConfig = Field(default_factory=LLMConfig)

    # Execution settings
    default_timeout: int = Field(default=120, ge=1, le=3600)
    max_retries: int = Field(default=3, ge=0, le=10)

    @classmethod
    def load(cls, config_path: Optional[Path] = None) -> "GSDConfig":
        """Load configuration from file or defaults.

        Args:
            config_path: Optional path to configuration file (YAML/JSON)

        Returns:
            GSDConfig instance
        """
        if config_path and config_path.exists():
            import yaml

            with open(config_path, encoding="utf-8") as f:
                data = yaml.safe_load(f) or {}

            # Convert nested dicts to proper types
            if "default_llm" in data and isinstance(data["default_llm"], dict):
                data["default_llm"] = LLMConfig(**data["default_llm"])

            # Convert string paths to Path objects
            for key in ("project_dir", "agents_dir", "sessions_dir"):
                if key in data and isinstance(data[key], str):
                    data[key] = Path(data[key])

            return cls(**data)

        return cls()

    def get_agents_path(self) -> Path:
        """Get full path to agents directory.

        Returns:
            Absolute path to agents directory
        """
        if self.agents_dir.is_absolute():
            return self.agents_dir
        return self.project_dir / self.agents_dir

    def get_sessions_path(self) -> Path:
        """Get full path to sessions directory.

        Returns:
            Absolute path to sessions directory
        """
        if self.sessions_dir.is_absolute():
            return self.sessions_dir
        return self.project_dir / self.sessions_dir
