# This file was auto-generated by Fern from our API Definition.

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.access_grant_list_response import AccessGrantListResponse
from ..types.access_grant_response import AccessGrantResponse
from ..types.access_overview_response import AccessOverviewResponse
from ..types.bulk_grant_entry import BulkGrantEntry
from ..types.resolved_access_response import ResolvedAccessResponse
from ..types.users_with_access_response import UsersWithAccessResponse

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawAccessControlClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def list_grants(
        self,
        organization_id: str,
        *,
        entity_type: typing.Optional[str] = None,
        entity_id: typing.Optional[str] = None,
        grantee_type: typing.Optional[str] = None,
        grantee_id: typing.Optional[str] = None,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AccessGrantListResponse]:
        """
        List access grants for an organization with optional filters.

        Includes both real AccessGrant records and synthesized grants
        from legacy VectorStore.access_mode.

        Parameters
        ----------
        organization_id : str

        entity_type : typing.Optional[str]

        entity_id : typing.Optional[str]

        grantee_type : typing.Optional[str]

        grantee_id : typing.Optional[str]

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants",
            method="GET",
            params={
                "entity_type": entity_type,
                "entity_id": entity_id,
                "grantee_type": grantee_type,
                "grantee_id": grantee_id,
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_grant(
        self,
        organization_id: str,
        *,
        entity_type: str,
        entity_id: str,
        grantee_type: str,
        grantee_id: str,
        access_level: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AccessGrantResponse]:
        """
        Create a new access grant.

        Parameters
        ----------
        organization_id : str

        entity_type : str

        entity_id : str

        grantee_type : str

        grantee_id : str

        access_level : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AccessGrantResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants",
            method="POST",
            json={
                "entity_type": entity_type,
                "entity_id": entity_id,
                "grantee_type": grantee_type,
                "grantee_id": grantee_id,
                "access_level": access_level,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantResponse,
                    parse_obj_as(
                        type_=AccessGrantResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_access_overview(
        self, organization_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[AccessOverviewResponse]:
        """
        Get a role-scoped access overview for the Access Overview page.

        Admins see all slices, stores, and grants. Regular users see only
        entities they have access to and grants for those entities.

        Parameters
        ----------
        organization_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AccessOverviewResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/overview",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessOverviewResponse,
                    parse_obj_as(
                        type_=AccessOverviewResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def bulk_create_grants(
        self,
        organization_id: str,
        *,
        entity_type: str,
        entity_id: str,
        grants: typing.Sequence[BulkGrantEntry],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[typing.List[AccessGrantResponse]]:
        """
        Create multiple access grants for the same entity.

        Parameters
        ----------
        organization_id : str

        entity_type : str

        entity_id : str

        grants : typing.Sequence[BulkGrantEntry]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[typing.List[AccessGrantResponse]]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants/bulk",
            method="POST",
            json={
                "entity_type": entity_type,
                "entity_id": entity_id,
                "grants": convert_and_respect_annotation_metadata(
                    object_=grants, annotation=typing.Sequence[BulkGrantEntry], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[AccessGrantResponse],
                    parse_obj_as(
                        type_=typing.List[AccessGrantResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def revoke_grant(
        self, organization_id: str, grant_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[None]:
        """
        Revoke (soft-delete) an access grant.

        Parameters
        ----------
        organization_id : str

        grant_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants/{jsonable_encoder(grant_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update_grant(
        self,
        organization_id: str,
        grant_id: str,
        *,
        access_level: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AccessGrantResponse]:
        """
        Update the access level of an existing grant.

        Parameters
        ----------
        organization_id : str

        grant_id : str

        access_level : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AccessGrantResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants/{jsonable_encoder(grant_id)}",
            method="PATCH",
            json={
                "access_level": access_level,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantResponse,
                    parse_obj_as(
                        type_=AccessGrantResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_slice_grants(
        self,
        organization_id: str,
        slice_id: str,
        *,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AccessGrantListResponse]:
        """
        List access grants for a specific knowledge slice.

        Includes both real AccessGrant records and synthesized grants
        from legacy VectorStore.access_mode on the slice's stores.

        Parameters
        ----------
        organization_id : str

        slice_id : str

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/knowledge/slices/{jsonable_encoder(slice_id)}/grants",
            method="GET",
            params={
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_store_grants(
        self,
        organization_id: str,
        store_id: str,
        *,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AccessGrantListResponse]:
        """
        List access grants for a specific vector store.

        Includes both real AccessGrant records and synthesized grants
        from legacy VectorStore.access_mode.

        Parameters
        ----------
        organization_id : str

        store_id : str

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/vector-stores/{jsonable_encoder(store_id)}/grants",
            method="GET",
            params={
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_assistant_grants(
        self,
        organization_id: str,
        assistant_id: str,
        *,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AccessGrantListResponse]:
        """
        List access grants for a specific assistant.

        Parameters
        ----------
        organization_id : str

        assistant_id : str

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/assistants/{jsonable_encoder(assistant_id)}/grants",
            method="GET",
            params={
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_resolved_access(
        self,
        organization_id: str,
        user_id: str,
        *,
        entity_type: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ResolvedAccessResponse]:
        """
        Compute effective access for a user across all entity types, split by slice and store.

        Parameters
        ----------
        organization_id : str

        user_id : str

        entity_type : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[ResolvedAccessResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/users/{jsonable_encoder(user_id)}/resolved-access",
            method="GET",
            params={
                "entity_type": entity_type,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ResolvedAccessResponse,
                    parse_obj_as(
                        type_=ResolvedAccessResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_users_with_access(
        self,
        organization_id: str,
        *,
        entity_type: str,
        entity_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UsersWithAccessResponse]:
        """
        Get all users who have access to a specific entity.

        Parameters
        ----------
        organization_id : str

        entity_type : str

        entity_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[UsersWithAccessResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/knowledge/users-with-access",
            method="GET",
            params={
                "entity_type": entity_type,
                "entity_id": entity_id,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UsersWithAccessResponse,
                    parse_obj_as(
                        type_=UsersWithAccessResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawAccessControlClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list_grants(
        self,
        organization_id: str,
        *,
        entity_type: typing.Optional[str] = None,
        entity_id: typing.Optional[str] = None,
        grantee_type: typing.Optional[str] = None,
        grantee_id: typing.Optional[str] = None,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AccessGrantListResponse]:
        """
        List access grants for an organization with optional filters.

        Includes both real AccessGrant records and synthesized grants
        from legacy VectorStore.access_mode.

        Parameters
        ----------
        organization_id : str

        entity_type : typing.Optional[str]

        entity_id : typing.Optional[str]

        grantee_type : typing.Optional[str]

        grantee_id : typing.Optional[str]

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants",
            method="GET",
            params={
                "entity_type": entity_type,
                "entity_id": entity_id,
                "grantee_type": grantee_type,
                "grantee_id": grantee_id,
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_grant(
        self,
        organization_id: str,
        *,
        entity_type: str,
        entity_id: str,
        grantee_type: str,
        grantee_id: str,
        access_level: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AccessGrantResponse]:
        """
        Create a new access grant.

        Parameters
        ----------
        organization_id : str

        entity_type : str

        entity_id : str

        grantee_type : str

        grantee_id : str

        access_level : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AccessGrantResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants",
            method="POST",
            json={
                "entity_type": entity_type,
                "entity_id": entity_id,
                "grantee_type": grantee_type,
                "grantee_id": grantee_id,
                "access_level": access_level,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantResponse,
                    parse_obj_as(
                        type_=AccessGrantResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_access_overview(
        self, organization_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[AccessOverviewResponse]:
        """
        Get a role-scoped access overview for the Access Overview page.

        Admins see all slices, stores, and grants. Regular users see only
        entities they have access to and grants for those entities.

        Parameters
        ----------
        organization_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AccessOverviewResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/overview",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessOverviewResponse,
                    parse_obj_as(
                        type_=AccessOverviewResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def bulk_create_grants(
        self,
        organization_id: str,
        *,
        entity_type: str,
        entity_id: str,
        grants: typing.Sequence[BulkGrantEntry],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[typing.List[AccessGrantResponse]]:
        """
        Create multiple access grants for the same entity.

        Parameters
        ----------
        organization_id : str

        entity_type : str

        entity_id : str

        grants : typing.Sequence[BulkGrantEntry]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[typing.List[AccessGrantResponse]]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants/bulk",
            method="POST",
            json={
                "entity_type": entity_type,
                "entity_id": entity_id,
                "grants": convert_and_respect_annotation_metadata(
                    object_=grants, annotation=typing.Sequence[BulkGrantEntry], direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[AccessGrantResponse],
                    parse_obj_as(
                        type_=typing.List[AccessGrantResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def revoke_grant(
        self, organization_id: str, grant_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Revoke (soft-delete) an access grant.

        Parameters
        ----------
        organization_id : str

        grant_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants/{jsonable_encoder(grant_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update_grant(
        self,
        organization_id: str,
        grant_id: str,
        *,
        access_level: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AccessGrantResponse]:
        """
        Update the access level of an existing grant.

        Parameters
        ----------
        organization_id : str

        grant_id : str

        access_level : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AccessGrantResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/access/grants/{jsonable_encoder(grant_id)}",
            method="PATCH",
            json={
                "access_level": access_level,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantResponse,
                    parse_obj_as(
                        type_=AccessGrantResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_slice_grants(
        self,
        organization_id: str,
        slice_id: str,
        *,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AccessGrantListResponse]:
        """
        List access grants for a specific knowledge slice.

        Includes both real AccessGrant records and synthesized grants
        from legacy VectorStore.access_mode on the slice's stores.

        Parameters
        ----------
        organization_id : str

        slice_id : str

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/knowledge/slices/{jsonable_encoder(slice_id)}/grants",
            method="GET",
            params={
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_store_grants(
        self,
        organization_id: str,
        store_id: str,
        *,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AccessGrantListResponse]:
        """
        List access grants for a specific vector store.

        Includes both real AccessGrant records and synthesized grants
        from legacy VectorStore.access_mode.

        Parameters
        ----------
        organization_id : str

        store_id : str

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/vector-stores/{jsonable_encoder(store_id)}/grants",
            method="GET",
            params={
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_assistant_grants(
        self,
        organization_id: str,
        assistant_id: str,
        *,
        skip: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AccessGrantListResponse]:
        """
        List access grants for a specific assistant.

        Parameters
        ----------
        organization_id : str

        assistant_id : str

        skip : typing.Optional[int]

        limit : typing.Optional[int]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AccessGrantListResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/assistants/{jsonable_encoder(assistant_id)}/grants",
            method="GET",
            params={
                "skip": skip,
                "limit": limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AccessGrantListResponse,
                    parse_obj_as(
                        type_=AccessGrantListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_resolved_access(
        self,
        organization_id: str,
        user_id: str,
        *,
        entity_type: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ResolvedAccessResponse]:
        """
        Compute effective access for a user across all entity types, split by slice and store.

        Parameters
        ----------
        organization_id : str

        user_id : str

        entity_type : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[ResolvedAccessResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/users/{jsonable_encoder(user_id)}/resolved-access",
            method="GET",
            params={
                "entity_type": entity_type,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ResolvedAccessResponse,
                    parse_obj_as(
                        type_=ResolvedAccessResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_users_with_access(
        self,
        organization_id: str,
        *,
        entity_type: str,
        entity_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UsersWithAccessResponse]:
        """
        Get all users who have access to a specific entity.

        Parameters
        ----------
        organization_id : str

        entity_type : str

        entity_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[UsersWithAccessResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/organizations/{jsonable_encoder(organization_id)}/knowledge/users-with-access",
            method="GET",
            params={
                "entity_type": entity_type,
                "entity_id": entity_id,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UsersWithAccessResponse,
                    parse_obj_as(
                        type_=UsersWithAccessResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        parse_obj_as(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
