from collections.abc import Iterable
from typing import Any

from fastapi import Depends
from starlette.requests import Request

from pyidentity.security.authorization import (
    AuthorizationHandlerContext,
    AuthorizationPolicyProvider,
    Authorize,
)

__all__ = ("authorize",)

from pyidentity.security.authorization import ClaimsAuthorize


def authorize(roles: Iterable[str] | str | None = None, policy: str | None = None) -> Any:
    """Indicates that the route or router to which this dependency is applied requires the specified authorization.

    :param roles: A list of roles that are allowed to access the resource.
    :param policy: Policy name that determines access to the resource.
    :return:
    :raise InvalidOperationException: If the specified policy name is not found.
    :raise AuthorizationError: If authorization failed.
    """

    async def call_authorize(request: Request) -> None:
        await Authorize(roles, policy)(AuthorizationHandlerContext(request), AuthorizationPolicyProvider())

    return Depends(call_authorize)


def claims_authorize(claim_type: str, *allowed_values: Any, authentication_scheme: str | None = None) -> Any:
    async def call_authorize(request: Request) -> None:
        await ClaimsAuthorize(claim_type, *allowed_values, authentication_scheme=authentication_scheme)(
            AuthorizationHandlerContext(request), AuthorizationPolicyProvider()
        )

    return Depends(call_authorize)
