"""Helpers for reading Azure Discovery configuration from files.

Configuration files map directly onto the AzureDiscoveryRequest model.
Supported formats: JSON (.json), TOML (.toml), YAML (.yaml/.yml).
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any, Dict

from ..adt_types import AzureDiscoveryRequest


def deep_merge(base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
    """Recursively merge dictionaries (override wins)."""

    merged: Dict[str, Any] = dict(base)
    for key, value in override.items():
        if isinstance(value, dict) and isinstance(merged.get(key), dict):
            merged[key] = deep_merge(merged[key], value)
        else:
            merged[key] = value
    return merged


def _load_json(text: str) -> Dict[str, Any]:
    payload = json.loads(text) if text.strip() else {}
    if payload is None:
        return {}
    if not isinstance(payload, dict):
        raise ValueError("JSON config must be an object at the top level")
    return payload


def _load_toml(text: str) -> Dict[str, Any]:
    import tomllib

    payload = tomllib.loads(text) if text.strip() else {}
    if payload is None:
        return {}
    if not isinstance(payload, dict):
        raise ValueError("TOML config must be a table at the top level")
    return payload


def _load_yaml(text: str) -> Dict[str, Any]:
    try:
        import yaml
    except ImportError as exc:  # pragma: no cover
        raise RuntimeError(
            "YAML config support requires PyYAML (pip install azure-discovery or pip install pyyaml)."
        ) from exc

    payload = yaml.safe_load(text) if text.strip() else {}
    if payload is None:
        return {}
    if not isinstance(payload, dict):
        raise ValueError("YAML config must be a mapping/object at the top level")
    return payload


def load_config_file(path: Path) -> Dict[str, Any]:
    """Load JSON/TOML/YAML config into a dict."""

    if not path:
        raise ValueError("path is required")

    resolved = Path(path).expanduser()
    text = resolved.read_text(encoding="utf-8")
    suffix = resolved.suffix.lower()

    if suffix == ".json":
        return _load_json(text)
    if suffix == ".toml":
        return _load_toml(text)
    if suffix in {".yaml", ".yml"}:
        return _load_yaml(text)

    # Fallback: try formats in a reasonable order.
    last_error: Exception | None = None
    for loader in (_load_json, _load_toml, _load_yaml):
        try:
            return loader(text)
        except Exception as exc:  # noqa: BLE001
            last_error = exc

    raise ValueError(f"Unsupported config format for {path}") from last_error


def load_request_from_file(path: Path) -> AzureDiscoveryRequest:
    """Load an AzureDiscoveryRequest from a config file."""

    payload = load_config_file(path)
    return AzureDiscoveryRequest.model_validate(payload)


def write_config_file(path: Path, data: Dict[str, Any], format: str = "json") -> None:
    """Write a config dict to JSON or YAML.

    Args:
        path: Output file path (parent directories created if needed).
        data: Config dict (e.g. AzureDiscoveryRequest.model_dump(mode='json')).
        format: 'json' or 'yaml'.

    Raises:
        ValueError: If format is not json or yaml.
    """
    path = Path(path).expanduser()
    path.parent.mkdir(parents=True, exist_ok=True)

    if format.lower() == "json":
        text = json.dumps(data, indent=2)
    elif format.lower() in ("yaml", "yml"):
        try:
            import yaml
        except ImportError as exc:  # pragma: no cover
            raise RuntimeError(
                "YAML config support requires PyYAML (pip install pyyaml)."
            ) from exc
        text = yaml.safe_dump(data, default_flow_style=False, sort_keys=False)
    else:
        raise ValueError(f"Unsupported write format: {format}. Use 'json' or 'yaml'.")

    path.write_text(text, encoding="utf-8")
