"""{{ display_name }} MCP server — generated by mcpify. Do not hand-edit.

The strict, stop-at-first-match configuration cascade (REQ-2.2): CLI flags
-> env vars -> local file (`./{{ project_name }}.config.yml`) -> home file
(`~/.{{ project_name }}/config.yml`) -> system file
(`/etc/{{ project_name }}/config.yml`) -> install-dir file -> built-in
defaults (`Config`'s own field defaults). Each layer is a plain dict merged
lowest-priority-first, then validated once through the typed `Config`
model — mirrors `targets::rust::steps::enterprise`'s `config_manager.rs`,
substituting `pydantic-settings`' typed model for `serde`'s.
"""

from __future__ import annotations

import os
from enum import Enum
from pathlib import Path
from typing import Any

import yaml
from pydantic import Field
from pydantic_settings import BaseSettings

from .errors import ConfigurationError

ENV_PREFIX = "{{ tool_prefix_env }}"
CONFIG_DIR_NAME = ".{{ project_name }}"
LOCAL_CONFIG_FILE = "{{ project_name }}.config.yml"
SYSTEM_CONFIG_FILE = Path("/etc/{{ project_name }}/config.yml")


class AuthMethod(str, Enum):
{%- if auth_methods | length == 0 %}
    NONE = "none"
{%- endif %}
{%- for method in auth_methods %}
    {{ method.class_name | upper }} = "{{ method.key }}"
{%- endfor %}


class Transport(str, Enum):
    STDIO = "stdio"
    HTTP = "http"


class Config(BaseSettings):
    url: str
    auth_method: AuthMethod
    # mcpify:versions:begin
    api_version: str = "{{ default_version_label }}"
    # mcpify:versions:end
    log_level: str = "info"
    rate_limit: int = 100
    timeout_ms: int = 30_000
    cache_size: int = 500
    retry_attempts: int = 3
    transport: Transport = Transport.STDIO
    host: str = "127.0.0.1"
    port: int = 3000
    cors_allow: str | None = Field(default=None)


def _home_dir() -> Path:
    return Path(os.environ.get("HOME", "."))


def _install_dir() -> Path:
    return Path(__file__).resolve().parent.parent


def _read_yaml_if_exists(path: Path) -> dict[str, Any]:
    try:
        contents = path.read_text()
    except OSError:
        return {}
    loaded = yaml.safe_load(contents)
    return loaded if isinstance(loaded, dict) else {}


_ENV_SUFFIXES = {
    "url": "URL",
    "auth_method": "AUTH_METHOD",
    "api_version": "API_VERSION",
    "log_level": "LOG_LEVEL",
    "transport": "TRANSPORT",
    "host": "HOST",
    "cors_allow": "CORS_ALLOW",
    "rate_limit": "RATE_LIMIT",
    "timeout_ms": "TIMEOUT_MS",
    "cache_size": "CACHE_SIZE",
    "retry_attempts": "RETRY_ATTEMPTS",
    "port": "PORT",
}


def _env_overrides() -> dict[str, Any]:
    overrides: dict[str, Any] = {}
    for config_key, env_suffix in _ENV_SUFFIXES.items():
        value = os.environ.get(f"{ENV_PREFIX}_{env_suffix}")
        if value is not None:
            overrides[config_key] = value
    return overrides


def load_config(cli_flags: dict[str, Any] | None = None) -> Config:
    layers = [
        cli_flags or {},
        _env_overrides(),
        _read_yaml_if_exists(Path(LOCAL_CONFIG_FILE)),
        _read_yaml_if_exists(_home_dir() / CONFIG_DIR_NAME / "config.yml"),
        _read_yaml_if_exists(SYSTEM_CONFIG_FILE),
        _read_yaml_if_exists(_install_dir() / "config.yml"),
    ]

    # Lowest-priority layer merged first, each higher-priority layer merged
    # on top — the first layer (`cli_flags`) always wins, matching the
    # cascade's stop-at-first-match ordering.
    merged: dict[str, Any] = {}
    for layer in reversed(layers):
        merged.update(layer)

    try:
        return Config(**merged)
    except Exception as err:  # pydantic.ValidationError, deliberately caught broadly
        raise ConfigurationError(f"invalid configuration: {err}") from err
