"""
Supreme 2 MAX MCP Server Configuration
Manages MCP-specific settings loaded from YAML (mcp_config.yml).

Technology Stack reference: "YAML (.supreme2l.yml) - Existing format, human-readable"
"""

from __future__ import annotations

import logging
from dataclasses import asdict, dataclass, field
from pathlib import Path
from typing import Optional

import yaml

logger = logging.getLogger(__name__)

# Validation boundaries
_VALID_LOG_LEVELS = frozenset({"DEBUG", "INFO", "WARNING", "ERROR"})
_MIN_CONCURRENT = 1
_MAX_CONCURRENT = 10
_MIN_TIMEOUT = 60
_MAX_TIMEOUT = 7200
_MIN_RATE_LIMIT = 10
_MAX_RATE_LIMIT = 1000


@dataclass
class MCPServerConfig:
    """MCP server runtime configuration with sensible defaults."""

    max_concurrent_scans: int = 1
    scan_timeout: int = 3600  # seconds
    cache_enabled: bool = True
    log_level: str = "INFO"
    workspace_root: Optional[str] = None  # None = auto-detect
    rate_limit_requests: int = 100  # per minute
    max_scan_history: int = 100  # keep last N scans


def _clamp(value: int, lo: int, hi: int) -> int:
    return max(lo, min(hi, value))


def validate_config(config: MCPServerConfig) -> MCPServerConfig:
    """Validate and clamp configuration values to acceptable ranges."""
    config.max_concurrent_scans = _clamp(
        config.max_concurrent_scans, _MIN_CONCURRENT, _MAX_CONCURRENT,
    )
    config.scan_timeout = _clamp(
        config.scan_timeout, _MIN_TIMEOUT, _MAX_TIMEOUT,
    )
    config.log_level = (
        config.log_level.upper()
        if isinstance(config.log_level, str)
        else "INFO"
    )
    if config.log_level not in _VALID_LOG_LEVELS:
        logger.warning(
            "Invalid log_level '%s', falling back to INFO", config.log_level,
        )
        config.log_level = "INFO"
    config.rate_limit_requests = _clamp(
        config.rate_limit_requests, _MIN_RATE_LIMIT, _MAX_RATE_LIMIT,
    )
    if config.max_scan_history < 1:
        config.max_scan_history = 100
    return config


class MCPConfigManager:
    """Load, validate, and persist MCP server configuration."""

    DEFAULT_PATH = Path.home() / ".supreme2l" / "mcp_config.yml"

    def __init__(self, config_path: Optional[Path] = None):
        self.config_path = config_path or self.DEFAULT_PATH
        self.config = self._load_config()

    # ------------------------------------------------------------------
    # Public API
    # ------------------------------------------------------------------

    def reload(self) -> MCPServerConfig:
        """Re-read configuration from disk."""
        self.config = self._load_config()
        return self.config

    def save_config(self, config: Optional[MCPServerConfig] = None) -> None:
        """Persist *config* (or the current config) to disk."""
        config = config or self.config
        self.config_path.parent.mkdir(parents=True, exist_ok=True)
        data = asdict(config)
        with open(self.config_path, "w", encoding="utf-8") as fh:
            yaml.dump(data, fh, default_flow_style=False, sort_keys=False)

    # ------------------------------------------------------------------
    # Internal
    # ------------------------------------------------------------------

    def _load_config(self) -> MCPServerConfig:
        if not self.config_path.exists():
            logger.info(
                "MCP config not found at %s — using defaults", self.config_path,
            )
            config = MCPServerConfig()
            # Persist defaults so users can discover and edit the file
            self.save_config(config)
            return validate_config(config)

        try:
            with open(self.config_path, encoding="utf-8") as fh:
                data = yaml.safe_load(fh) or {}
        except Exception:
            logger.warning(
                "Failed to parse %s — using defaults", self.config_path,
                exc_info=True,
            )
            return validate_config(MCPServerConfig())

        # Only pass known fields to the dataclass
        known_fields = {f.name for f in MCPServerConfig.__dataclass_fields__.values()}
        filtered = {k: v for k, v in data.items() if k in known_fields}
        config = MCPServerConfig(**filtered)
        return validate_config(config)
