"""
Copyright (C) 2025 Luciano Guerche

This file is part of rabbitmq-mcp-server.

rabbitmq-mcp-server is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

rabbitmq-mcp-server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with rabbitmq-mcp-server. If not, see <https://www.gnu.org/licenses/>.
"""

import os
import time
from pathlib import Path
from typing import Any

import structlog

from config.loader import load_toml_config
from config.settings import Settings

logger = structlog.get_logger(__name__)


def load_settings(cli_args: dict[str, Any] | None = None) -> Settings:
    """
    Load settings with precedence: CLI args > env vars > TOML > .env > defaults.

    Args:
        cli_args: Optional dictionary of CLI argument overrides

    Returns:
        Validated Settings instance

    Raises:
        ValueError: If configuration validation fails
    """
    start_time = time.perf_counter()

    # Determine TOML config file path (AC #3)
    config_file_path = None
    if cli_args and "config_file" in cli_args:
        config_file_path = Path(cli_args["config_file"])
    elif os.getenv("CONFIG_FILE"):
        env_path = os.getenv("CONFIG_FILE")
        config_file_path = Path(env_path) if env_path else Path("config/config.toml")
    else:
        config_file_path = Path("config/config.toml")

    # Load TOML configuration
    toml_config = load_toml_config(config_file_path)

    try:
        # Build merged config dict with correct precedence
        # Precedence: CLI args > env vars > TOML > defaults (Pydantic handles defaults)

        # Cache env vars to avoid repeated os.getenv() calls (performance optimization)
        env_cache = (
            {key.upper(): os.getenv(key.upper()) for key in toml_config.keys()}
            if toml_config
            else {}
        )

        # Start with TOML values where no env var exists
        merged_config = {}
        if toml_config:
            for key, value in toml_config.items():
                env_key = key.upper()
                if not env_cache.get(env_key):
                    merged_config[key] = value

        # Apply CLI overrides (highest precedence)
        if cli_args:
            merged_config.update({k: v for k, v in cli_args.items() if v is not None})

        # Create Settings once with merged config (avoids multiple model_copy calls)
        # Pydantic will layer: defaults < merged_config < env vars automatically
        # But we need to pass merged_config as constructor args to ensure they override defaults
        # while still allowing env vars to override everything

        # Actually, Pydantic constructor args override env vars, so we need to be more careful
        # Solution: Only pass values to constructor that should override env vars (CLI args only)
        # For TOML, we already filtered out env vars above
        settings = Settings(**merged_config)

        # Log configuration loading time (AC #7)
        load_time_ms = (time.perf_counter() - start_time) * 1000
        logger.info(
            "configuration_loaded",
            load_time_ms=f"{load_time_ms:.2f}",
            config_file=(
                str(config_file_path) if config_file_path.exists() else "not found"
            ),
            amqp_host=settings.amqp_host,
            amqp_port=settings.amqp_port,
            http_host=settings.http_host,
            http_port=settings.http_port,
        )

        if load_time_ms > 100:
            logger.warning(
                "configuration_load_slow",
                load_time_ms=f"{load_time_ms:.2f}",
                threshold_ms=100,
            )

        return settings

    except Exception as e:
        logger.error("configuration_load_failed", error=str(e))
        raise


__all__ = ["Settings", "load_settings", "load_toml_config"]
