from __future__ import annotations

from dataclasses import dataclass
from typing import Callable
from fastapi import HTTPException, status


@dataclass(frozen=True)
class ErrorMappingRule:
    predicate: Callable[[str], bool]
    status_code: int
    detail: str | Callable[[str], str]


class AuthorizationHttpErrorMapper:
    def __init__(self, rules: list[ErrorMappingRule]):
        self._rules = rules

    def map(self, error: ValueError) -> HTTPException:
        message = str(error)
        lowered = message.lower()
        for rule in self._rules:
            if rule.predicate(lowered):
                detail = rule.detail(message) if callable(rule.detail) else rule.detail
                return HTTPException(status_code=rule.status_code, detail=detail)
        return HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Access denied",
        )

    @classmethod
    def default(cls) -> "AuthorizationHttpErrorMapper":
        rules = [
            ErrorMappingRule(
                predicate=lambda message: "not authenticated" in message,
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail=lambda message: message,
            ),
            ErrorMappingRule(
                predicate=lambda message: "not found" in message,
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Agent not found",
            ),
        ]
        return cls(rules)
