"""Application settings — load/save TOML config for AgentScout."""

from __future__ import annotations

import logging
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any

logger = logging.getLogger(__name__)

# Default config directory
DEFAULT_CONFIG_DIR = Path.home() / ".agent-scout"
DEFAULT_CONFIG_FILE = DEFAULT_CONFIG_DIR / "config.toml"


@dataclass
class LLMSettings:
    """LLM-related settings."""

    default_model: str = "anthropic/claude-sonnet-4-20250514"
    temperature: float = 0.3
    max_tokens: int = 4096
    fast_model: str = "anthropic/claude-haiku-3"
    best_model: str = "anthropic/claude-sonnet-4-20250514"
    enable_routing: bool = True


@dataclass
class BudgetSettings:
    """Budget-related settings."""

    task_limit: float = 1.0
    daily_limit: float = 10.0
    monthly_limit: float = 50.0
    enforce: bool = True


@dataclass
class CustomEndpointSettings:
    """A user-defined LLM endpoint."""

    name: str = ""
    base_url: str = ""
    api_key: str = ""
    model_name: str = ""


@dataclass
class SearchSettings:
    """Search provider settings."""

    tavily_api_key: str = ""
    serpapi_api_key: str = ""
    brave_api_key: str = ""


@dataclass
class Settings:
    """Root settings object for AgentScout."""

    llm: LLMSettings = field(default_factory=LLMSettings)
    budget: BudgetSettings = field(default_factory=BudgetSettings)
    search: SearchSettings = field(default_factory=SearchSettings)
    custom_endpoints: list[CustomEndpointSettings] = field(default_factory=list)
    plugins: list[str] = field(
        default_factory=lambda: [
            "web_search",
            "browser",
            "price_tracker",
            "notifier",
            "exporter",
        ]
    )
    personality: str = "helpful"
    autonomy: str = "full"
    verbose: bool = False
    config_dir: str = str(DEFAULT_CONFIG_DIR)


def load_settings(config_path: Path | None = None) -> Settings:
    """Load settings from a TOML config file."""
    path = config_path or DEFAULT_CONFIG_FILE
    settings = Settings()

    if not path.exists():
        return settings

    try:
        import tomllib

        with open(path, "rb") as f:
            data = tomllib.load(f)

        _apply_dict(settings, data)
    except Exception:
        logger.warning("Failed to load config from %s", path, exc_info=True)

    return settings


def save_settings(settings: Settings, config_path: Path | None = None) -> None:
    """Save settings to a TOML config file."""
    path = config_path or DEFAULT_CONFIG_FILE
    path.parent.mkdir(parents=True, exist_ok=True)

    lines = _settings_to_toml(settings)
    path.write_text(lines)


def _apply_dict(settings: Settings, data: dict[str, Any]) -> None:
    """Apply a parsed TOML dict onto a Settings object."""
    if "llm" in data and isinstance(data["llm"], dict):
        for k, v in data["llm"].items():
            if hasattr(settings.llm, k):
                setattr(settings.llm, k, v)

    if "budget" in data and isinstance(data["budget"], dict):
        for k, v in data["budget"].items():
            if hasattr(settings.budget, k):
                setattr(settings.budget, k, v)

    if "search" in data and isinstance(data["search"], dict):
        for k, v in data["search"].items():
            if hasattr(settings.search, k):
                setattr(settings.search, k, v)

    if "custom_endpoints" in data and isinstance(data["custom_endpoints"], list):
        settings.custom_endpoints = [
            CustomEndpointSettings(**ep) for ep in data["custom_endpoints"]
        ]

    if "plugins" in data and isinstance(data["plugins"], list):
        settings.plugins = data["plugins"]

    for key in ("personality", "autonomy", "verbose", "config_dir"):
        if key in data:
            setattr(settings, key, data[key])


def _settings_to_toml(settings: Settings) -> str:
    """Serialize settings to TOML string."""
    lines: list[str] = []

    # Top-level
    lines.append(f'personality = "{settings.personality}"')
    lines.append(f'autonomy = "{settings.autonomy}"')
    lines.append(f"verbose = {str(settings.verbose).lower()}")
    lines.append(f"plugins = {_list_to_toml(settings.plugins)}")
    lines.append("")

    # LLM
    lines.append("[llm]")
    lines.append(f'default_model = "{settings.llm.default_model}"')
    lines.append(f"temperature = {settings.llm.temperature}")
    lines.append(f"max_tokens = {settings.llm.max_tokens}")
    lines.append(f'fast_model = "{settings.llm.fast_model}"')
    lines.append(f'best_model = "{settings.llm.best_model}"')
    lines.append(f"enable_routing = {str(settings.llm.enable_routing).lower()}")
    lines.append("")

    # Budget
    lines.append("[budget]")
    lines.append(f"task_limit = {settings.budget.task_limit}")
    lines.append(f"daily_limit = {settings.budget.daily_limit}")
    lines.append(f"monthly_limit = {settings.budget.monthly_limit}")
    lines.append(f"enforce = {str(settings.budget.enforce).lower()}")
    lines.append("")

    # Search
    lines.append("[search]")
    lines.append(f'tavily_api_key = "{settings.search.tavily_api_key}"')
    lines.append(f'serpapi_api_key = "{settings.search.serpapi_api_key}"')
    lines.append(f'brave_api_key = "{settings.search.brave_api_key}"')
    lines.append("")

    # Custom endpoints
    for ep in settings.custom_endpoints:
        lines.append("[[custom_endpoints]]")
        lines.append(f'name = "{ep.name}"')
        lines.append(f'base_url = "{ep.base_url}"')
        lines.append(f'api_key = "{ep.api_key}"')
        lines.append(f'model_name = "{ep.model_name}"')
        lines.append("")

    return "\n".join(lines) + "\n"


def _list_to_toml(items: list[str]) -> str:
    """Format a list of strings as TOML array."""
    quoted = ", ".join(f'"{item}"' for item in items)
    return f"[{quoted}]"
