"""ValidatorRegistry — thread-safe registry for limit validators."""

from __future__ import annotations

import threading
from typing import Any, Callable

from pyfortis._types import (
    Exposure,
    LimitCheckResult,
    LimitSpec,
    Order,
    Position,
)
from pyfortis.errors import ValidatorNotFoundError

ValidatorFn = Callable[
    [LimitSpec, Order, dict[str, Position], dict[str, Exposure], dict[str, Any]],
    LimitCheckResult,
]


class ValidatorRegistry:
    """Thread-safe registry for limit validators."""

    def __init__(self) -> None:
        self._validators: dict[str, ValidatorFn] = {}
        self._lock = threading.Lock()

    def register(self, name: str, fn: ValidatorFn) -> None:
        with self._lock:
            self._validators[name] = fn

    def get(self, name: str) -> ValidatorFn | None:
        with self._lock:
            return self._validators.get(name)

    def has(self, name: str) -> bool:
        with self._lock:
            return name in self._validators

    def names(self) -> list[str]:
        with self._lock:
            return list(self._validators.keys())

    def decorator(self, name: str) -> Callable[[ValidatorFn], ValidatorFn]:
        def wrapper(fn: ValidatorFn) -> ValidatorFn:
            self.register(name, fn)
            return fn
        return wrapper

    def validate(
        self,
        limit: LimitSpec,
        order: Order,
        positions: dict[str, Position],
        exposures: dict[str, Exposure],
        context: dict[str, Any],
    ) -> LimitCheckResult:
        fn = self.get(limit.type.value)
        if fn is None:
            raise ValidatorNotFoundError(
                f"No validator registered for '{limit.type.value}'",
                context={"limit_name": limit.name, "limit_type": limit.type.value},
            )
        return fn(limit, order, positions, exposures, context)
