import pydantic
import inspect
import collections

from typing import (
	TypeVar,
	Callable,
	Any,
	Optional,
	Mapping,
	cast,
)

P = TypeVar('P')
R = TypeVar('R')


def validate_params(view: Callable[..., R]) -> Callable[..., R]:
	class Parameter:
		kind: Any
		annotation: Any

	parameters = cast(Mapping[str, Parameter], inspect.signature(view).parameters)

	positional_parameters: collections.OrderedDict[str, type[Any]] = collections.OrderedDict(
		(
			(k, v.annotation)
			for k, v in parameters.items()
			if v.kind
			in (
				inspect.Parameter.POSITIONAL_ONLY,
				inspect.Parameter.POSITIONAL_OR_KEYWORD,
			)
		)
	)
	positional_names = list(positional_parameters)

	model = pydantic.create_model(
		getattr(view, '__name__'),
		**{
			k: v.annotation
			for k, v in parameters.items()
			if v.kind
			in (
				inspect.Parameter.POSITIONAL_OR_KEYWORD,
				inspect.Parameter.POSITIONAL_ONLY,
				inspect.Parameter.KEYWORD_ONLY,
			)
		},
		__config__=pydantic.ConfigDict(
			arbitrary_types_allowed=True,
		),
	)

	def wrapper(*args: Any, **kwargs: Any) -> R:
		# data = model.model_validate(

		kwargs_to_check: dict[str, Any] = {k: v for k, v in kwargs.items()}

		for i, o in enumerate(args):
			k = positional_names[i]

			parameter = positional_parameters[k]

			assert not k in kwargs_to_check

			kwargs_to_check[k] = o

		model.model_validate(
			kwargs_to_check,
		)
		# ).dict()

		return view(
			# **data,
			*args,
			**kwargs,
		)

	return wrapper
