"""Configuration models with validation."""

from pathlib import Path
from typing import Optional, Literal
from pydantic import BaseModel, Field, field_validator
import yaml


class ProviderConfig(BaseModel):
    """Configuration for a single AI provider."""
    enabled: bool = True
    key: str = Field(default="", description="API key")
    models: list[str] = Field(default_factory=list, description="List of model names")
    base_url: str = Field(default="", description="Custom base URL")


class AIConfig(BaseModel):
    """AI provider configuration including Kimi (Moonshot AI).
    
    Supports both single provider (legacy) and multi-provider modes.
    """

    # Legacy single provider mode
    provider: Literal[
        "anthropic",    # Claude
        "openai",       # GPT-4, GPT-3.5
        "kimi",         # Moonshot AI (Kimi K2.5)
        "openrouter",   # Multi-model gateway
        "ollama",       # Local models
        "google",       # Gemini
    ] = Field(default="anthropic", description="AI provider")

    key: str = Field(default="", description="API key")
    model: str = Field(default="", description="Model name (auto-selected if empty)")
    base_url: str = Field(default="", description="Custom API endpoint")
    
    # Multi-provider mode (OpenClaw 2026.3.13+)
    providers: dict[str, ProviderConfig] = Field(
        default_factory=dict,
        description="Multiple provider configurations"
    )

    def get_base_url(self) -> str:
        """Return provider base URL."""
        if self.base_url:
            return self.base_url
        urls = {
            "anthropic": "https://api.anthropic.com",
            "openai": "https://api.openai.com",
            "kimi": "https://api.moonshot.cn/v1",
            "openrouter": "https://openrouter.ai/api",
            "ollama": "http://localhost:11434",
            "google": "https://generativelanguage.googleapis.com",
        }
        return urls.get(self.provider, "")

    def get_default_model(self) -> str:
        """Return default model for provider."""
        defaults = {
            "anthropic": "claude-3-5-sonnet",
            "openai": "gpt-4o",
            "kimi": "kimi-k2.5",
            "openrouter": "anthropic/claude-3.5-sonnet",
            "ollama": "llama3.2",
            "google": "gemini-3-pro",
        }
        return self.model or defaults.get(self.provider, "")


class ChannelsConfig(BaseModel):
    """Messaging channel configuration."""
    web: bool = True
    whatsapp: bool = False
    telegram: bool = False
    telegram_token: str = ""
    discord: bool = False
    discord_token: str = ""
    slack: bool = False
    slack_token: str = ""
    signal: bool = False


class GatewayConfig(BaseModel):
    """Gateway service configuration."""
    port: int = 18789
    autostart: bool = True
    verbose: bool = False


class AutomationConfig(BaseModel):
    """Automation and auto-login configuration."""
    auto_open_dashboard: bool = Field(
        default=True, 
        description="Automatically open dashboard after installation"
    )
    auto_login: bool = Field(
        default=True,
        description="Automatically login to dashboard without user interaction"
    )
    browser_path: str = Field(
        default="",
        description="Path to browser executable (empty = use system default)"
    )
    startup_timeout: int = Field(
        default=30,
        description="Seconds to wait for gateway to start"
    )


class Config(BaseModel):
    """Main configuration."""

    version: str = "latest"
    ai: AIConfig = Field(default_factory=AIConfig)
    channels: ChannelsConfig = Field(default_factory=ChannelsConfig)
    gateway: GatewayConfig = Field(default_factory=GatewayConfig)
    automation: AutomationConfig = Field(default_factory=AutomationConfig)

    @classmethod
    def from_yaml(cls, path: Path) -> "Config":
        """Load from YAML file."""
        with open(path) as f:
            data = yaml.safe_load(f)
        return cls.model_validate(data)

    def to_env(self) -> dict:
        """Convert to environment variables for OpenClaw."""
        env = {
            "OPENCLAW_PROVIDER": self.ai.provider,
            "OPENCLAW_MODEL": self.ai.model or self.ai.get_default_model(),
            "OPENCLAW_API_KEY": self.ai.key,
            "OPENCLAW_BASE_URL": self.ai.get_base_url(),
            "OPENCLAW_PORT": str(self.gateway.port),
        }
        return {k: v for k, v in env.items() if v}


def generate_example_config() -> str:
    """Generate example YAML configuration."""
    return """# OpenClaw Installer Configuration
# ================================
# Quick start: edit this file, then run:
#   openclaw-installer --config this-file.yaml

# AI Provider
# -----------
# Two modes supported:
# 1. Single provider (legacy) - use 'provider', 'key', 'model'
# 2. Multi-provider (OpenClaw 2026.3.13+) - use 'providers' dictionary

# === SINGLE PROVIDER MODE ===
# ai:
#   provider: anthropic
#   key: ""  # Your API key here
#   model: "claude-3-5-sonnet"

# === MULTI-PROVIDER MODE (Recommended) ===
# Configure multiple AI providers simultaneously
ai:
  providers:
    ollama:
      enabled: true
      base_url: "http://localhost:11434"
      models: ["llama3.2"]
    
    google:
      enabled: true
      key: ""  # YOUR_GEMINI_API_KEY
      models: ["gemini-3-pro"]
    
    anthropic:
      enabled: true
      key: ""  # YOUR_ANTHROPIC_API_KEY
      models: ["claude-3-7-sonnet-20250219"]
    
    moonshotai:
      enabled: true
      base_url: "https://api.moonshot.cn/v1"
      key: ""  # YOUR_KIMI_API_KEY
      models: ["kimi-k2.5"]

# Channels
# --------
channels:
  web: true        # Web UI at http://localhost:18789
  whatsapp: false
  telegram: false
  telegram_token: ""
  discord: false
  discord_token: ""
  slack: false
  slack_token: ""
  signal: false

# Gateway
gateway:
  port: 18789
  autostart: true
  verbose: false

# Automation (optional)
# ---------------------
# Configure automatic dashboard login and startup behavior
automation:
  # Automatically open dashboard after installation
  auto_open_dashboard: true
  
  # Automatically login without requiring manual token entry
  # This follows the "How to connect" steps:
  #   1. Start the gateway on your host machine
  #   2. Get a tokenized dashboard URL  
  #   3. Open the browser with the authenticated URL
  auto_login: true
  
  # Path to browser executable (leave empty for system default)
  # Examples:
  #   Windows: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
  #   macOS: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
  #   Linux: "/usr/bin/google-chrome"
  browser_path: ""
  
  # Seconds to wait for gateway to start before timeout
  startup_timeout: 30
"""


def generate_default_config() -> str:
    """Generate default multi-provider YAML configuration.
    
    Creates a config with all major providers enabled (placeholders for API keys).
    """
    return """# OpenClaw Default Multi-Provider Configuration
# ============================================
# This is the default configuration used when no --config is provided.
# Edit the API keys below or provide your own config file.

version: latest

# AI Providers (Multi-Provider Mode)
# ----------------------------------
# All providers are enabled by default. Add your API keys below.
ai:
  providers:
    # Local Ollama (no API key needed)
    ollama:
      enabled: true
      base_url: "http://localhost:11434"
      models: ["llama3.2"]
    
    # Google Gemini
    google:
      enabled: true
      key: ""  # Add your Gemini API key here
      models: ["gemini-3-pro"]
    
    # Anthropic Claude
    anthropic:
      enabled: true
      key: ""  # Add your Anthropic API key here
      models: ["claude-3-7-sonnet-20250219"]
    
    # Moonshot AI (Kimi)
    moonshotai:
      enabled: true
      base_url: "https://api.moonshot.cn/v1"
      key: ""  # Add your Moonshot API key here
      models: ["kimi-k2.5"]

# Gateway Settings
gateway:
  port: 18789
  autostart: true
  verbose: false

# Channels (Web UI enabled by default)
channels:
  web: true
  whatsapp: false
  telegram: false
  discord: false
  slack: false
  signal: false

# Automation
automation:
  auto_open_dashboard: true
  auto_login: true
  browser_path: ""
  startup_timeout: 30
"""
