from __future__ import annotations

from pathlib import Path
from importlib import resources
from typing import Any, Dict, List

import yaml


_DEFAULT_SCHEMA_PATH = resources.files("analogai.foundation.config") / "schema.yaml"


def validate_settings(settings, schema_path: str | Path = _DEFAULT_SCHEMA_PATH) -> None:
    schema_file = Path(schema_path)
    if not schema_file.exists():
        return

    schema = yaml.safe_load(schema_file.read_text(encoding="utf-8")) or {}
    errors: List[str] = []

    type_map = {
        "str": str,
        "bool": bool,
        "float": float,
        "int": int,
        "list": list,
        "dict": dict,
    }

    def is_missing(value: Any) -> bool:
        if value is None:
            return True
        if isinstance(value, str) and value.strip() == "":
            return True
        return False

    def walk(node: Dict[str, Any], prefix: str = "") -> None:
        for key, value in node.items():
            path = f"{prefix}.{key}" if prefix else key
            if isinstance(value, dict) and "type" in value and isinstance(value.get("type"), str):
                expected_type = value.get("type")
                required = bool(value.get("required", False))
                enum = value.get("enum")
                actual = settings.get(path, None)

                if is_missing(actual):
                    if required:
                        errors.append(f"Missing required config: {path}")
                    continue

                if expected_type not in type_map:
                    errors.append(f"Unknown type '{expected_type}' for {path}")
                    continue

                if not isinstance(actual, type_map[expected_type]):
                    errors.append(
                        f"Invalid type for {path}: expected {expected_type}, got {type(actual).__name__}"
                    )
                    continue

                if enum and actual not in enum:
                    errors.append(
                        f"Invalid value for {path}: '{actual}' not in {enum}"
                    )
                continue

            if isinstance(value, dict):
                walk(value, path)

    walk(schema)

    if errors:
        error_text = "\n".join(f"- {msg}" for msg in errors)
        raise ValueError(f"Config validation failed:\n{error_text}")
