"""YAML-based configuration loader."""

from __future__ import annotations

import logging
import os
from pathlib import Path
from typing import Any

import yaml

logger = logging.getLogger(__name__)

# Valid top-level keys and pipeline sub-keys for agent configs.
_VALID_TOP_LEVEL_KEYS = {
    "pipeline", "models", "system_prompt", "llm_streaming", "audio",
    "llm_hook", "llm_stream_hook", "barge_in_hook", "webhook",
    "transport", "strands", "name",
}
_VALID_PIPELINE_KEYS = {
    "stt", "tts", "llm", "vad", "vad_threshold", "barge_in_enabled",
    "silence_duration_ms",
}


def validate_config(config: dict[str, Any]) -> list[str]:
    """Validate a config dict and return a list of warnings.

    Checks for unknown keys (likely typos) and basic type correctness.
    Warnings are non-fatal but logged — callers decide whether to raise.
    """
    warnings: list[str] = []
    if not isinstance(config, dict):
        return ["Config must be a YAML mapping (dict)"]

    for key in config:
        if key not in _VALID_TOP_LEVEL_KEYS:
            warnings.append(f"Unknown top-level config key: '{key}'")

    pipeline_cfg = config.get("pipeline", {})
    if isinstance(pipeline_cfg, dict):
        for key in pipeline_cfg:
            if key not in _VALID_PIPELINE_KEYS:
                warnings.append(f"Unknown pipeline config key: '{key}'")

        vad_threshold = pipeline_cfg.get("vad_threshold")
        if vad_threshold is not None:
            try:
                val = float(vad_threshold)
                if not 0.0 <= val <= 1.0:
                    warnings.append(f"vad_threshold should be 0.0–1.0, got {val}")
            except (ValueError, TypeError):
                warnings.append(f"vad_threshold must be a number, got '{vad_threshold}'")

        silence_ms = pipeline_cfg.get("silence_duration_ms")
        if silence_ms is not None:
            try:
                val = int(silence_ms)
                if val < 0:
                    warnings.append(f"silence_duration_ms must be positive, got {val}")
            except (ValueError, TypeError):
                warnings.append(f"silence_duration_ms must be an integer, got '{silence_ms}'")
    elif pipeline_cfg is not None:
        warnings.append("'pipeline' must be a mapping (dict)")

    models_cfg = config.get("models", {})
    if isinstance(models_cfg, dict):
        for name, model_cfg in models_cfg.items():
            if not isinstance(model_cfg, dict):
                warnings.append(f"Model '{name}' config must be a mapping")
                continue
            if "type" not in model_cfg:
                warnings.append(f"Model '{name}' missing required 'type' field")
            elif model_cfg["type"] not in ("stt", "tts", "llm", "vad"):
                warnings.append(f"Model '{name}' has invalid type: '{model_cfg['type']}'")
            if "class" not in model_cfg:
                warnings.append(f"Model '{name}' missing required 'class' field")

    return warnings


def load_config(path: str | Path = "config.yaml") -> dict[str, Any]:
    """Load configuration from a YAML file."""
    path = Path(path)
    if not path.exists():
        raise FileNotFoundError(f"Config file not found: {path}")
    with open(path) as f:
        config = yaml.safe_load(f)

    warnings = validate_config(config)
    for w in warnings:
        logger.warning("Config validation: %s", w)

    return config


def load_config_from_env() -> dict[str, Any] | None:
    """Load configuration from the AGENT_CONFIG_YAML environment variable.

    Returns the parsed dict, or None if the env var is not set.
    """
    raw = os.environ.get("AGENT_CONFIG_YAML")
    if not raw:
        return None
    logger.info("Loading config from AGENT_CONFIG_YAML env var")
    config = yaml.safe_load(raw)

    if config:
        warnings = validate_config(config)
        for w in warnings:
            logger.warning("Config validation: %s", w)

    return config
