from __future__ import annotations

import re
from typing import Any, Callable, cast

from pydantic import BaseModel

from .schemas import generated_schemas


def _to_class_name(schema_name: str) -> str:
    parts = re.split(r"[^0-9a-zA-Z]+", schema_name)
    return "".join(part[:1].upper() + part[1:] for part in parts if part)


def resolve_model(ref: str) -> type[BaseModel] | None:
    name = ref.split("/")[-1]
    class_name = _to_class_name(name)
    model = getattr(generated_schemas, class_name, None)
    if isinstance(model, type) and issubclass(model, BaseModel):
        return model
    return None


def get_validator(schema: dict[str, Any]) -> Callable[[Any], Any]:
    if "$ref" in schema:
        model = resolve_model(schema["$ref"])
        if model is not None:
            return cast(Callable[[Any], Any], model.model_validate)
    if schema.get("type") == "array" and isinstance(schema.get("items"), dict):
        items = schema["items"]
        if "$ref" in items:
            model = resolve_model(items["$ref"])
            if model is not None:
                def _validate_list(payload: Any) -> Any:
                    if not isinstance(payload, list):
                        raise ValueError("Expected list payload")
                    return [model.model_validate(item) for item in payload]

                return cast(Callable[[Any], Any], _validate_list)
    raise LookupError("No Pydantic validator for schema")
