from __future__ import annotations

import inspect
from functools import wraps
from typing import Any, Callable, get_type_hints


def validate_args(func: Callable[..., Any]) -> Callable[..., Any]:
    """Lightweight runtime validator stub.

    - Reads type hints and ensures simple primitives match (int/float/str/bool/list)
    - Placeholder for Satya integration
    """

    hints = get_type_hints(func)

    def coerce(name: str, value: Any, hint: Any) -> Any:
        # Minimal coercion/validation for common primitives.
        try:
            origin = getattr(hint, "__origin__", None)
            if hint in (int, float, str, bool):
                return hint(value)
            if origin is list:
                (elem_type,) = getattr(hint, "__args__", (str,))
                return [coerce(name, v, elem_type) for v in value]
        except Exception as e:  # pragma: no cover - keep permissive
            raise TypeError(f"Invalid value for {name}: {value!r} -> {hint}") from e
        return value

    @wraps(func)
    def wrapper(*args: Any, **kwargs: Any):
        sig = inspect.signature(func)
        allowed = set(sig.parameters.keys())
        # Drop any unexpected kwargs defensively
        safe_kwargs = {k: v for k, v in kwargs.items() if k in allowed}
        bound = sig.bind_partial(*args, **safe_kwargs)
        bound.apply_defaults()
        for k, v in list(bound.arguments.items()):
            hint = hints.get(k)
            if hint is not None and v is not None:
                bound.arguments[k] = coerce(k, v, hint)
        return func(*bound.args, **bound.kwargs)
    return wrapper
