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

import typing
import urllib.parse
from json.decoder import JSONDecodeError

from .....core.api_error import ApiError
from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .....core.jsonable_encoder import jsonable_encoder
from .....core.remove_none_from_dict import remove_none_from_dict
from ....commons.types.claim_id import ClaimId
from ....commons.types.page_token import PageToken
from ....commons.types.patient_external_id import PatientExternalId
from ....commons.types.provider_id import ProviderId
from ....commons.types.service_line_id import ServiceLineId
from ....commons.types.sort_direction import SortDirection
from ....financials.types.account_type import AccountType
from ....payers.resources.v_3.types.payer_uuid import PayerUuid
from .types.create_write_offs_response import CreateWriteOffsResponse
from .types.write_off import WriteOff
from .types.write_off_create import WriteOffCreate
from .types.write_off_id import WriteOffId
from .types.write_off_sort_field import WriteOffSortField
from .types.write_offs_page import WriteOffsPage

try:
    import pydantic.v1 as pydantic  # type: ignore
except ImportError:
    import pydantic  # type: ignore

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


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

    def get_multi(
        self,
        *,
        limit: typing.Optional[int] = None,
        patient_external_id: typing.Optional[PatientExternalId] = None,
        payer_uuid: typing.Optional[PayerUuid] = None,
        service_line_id: typing.Optional[ServiceLineId] = None,
        claim_id: typing.Optional[ClaimId] = None,
        billing_provider_id: typing.Optional[ProviderId] = None,
        sort: typing.Optional[WriteOffSortField] = None,
        sort_direction: typing.Optional[SortDirection] = None,
        page_token: typing.Optional[PageToken] = None,
        account_types: typing.Optional[typing.Union[AccountType, typing.List[AccountType]]] = None,
    ) -> WriteOffsPage:
        """
        Returns all write-offs satisfying the search criteria.

        Parameters:
            - limit: typing.Optional[int]. Defaults to 100. The value must be greater than 0 and less than 1000.

            - patient_external_id: typing.Optional[PatientExternalId].

            - payer_uuid: typing.Optional[PayerUuid].

            - service_line_id: typing.Optional[ServiceLineId].

            - claim_id: typing.Optional[ClaimId].

            - billing_provider_id: typing.Optional[ProviderId].

            - sort: typing.Optional[WriteOffSortField]. Defaults to write_off_timestamp

            - sort_direction: typing.Optional[SortDirection]. Sort direction. Defaults to descending order if not provided.

            - page_token: typing.Optional[PageToken].

            - account_types: typing.Optional[typing.Union[AccountType, typing.List[AccountType]]]. Filters the returned values to include only the provided account types.
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/write-offs/v1"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "patient_external_id": patient_external_id,
                    "payer_uuid": jsonable_encoder(payer_uuid),
                    "service_line_id": jsonable_encoder(service_line_id),
                    "claim_id": jsonable_encoder(claim_id),
                    "billing_provider_id": jsonable_encoder(billing_provider_id),
                    "sort": sort,
                    "sort_direction": sort_direction,
                    "page_token": page_token,
                    "account_types": account_types,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(WriteOffsPage, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(self, write_off_id: WriteOffId) -> WriteOff:
        """
        Retrieves a previously created write off by its `write_off_id`.

        Parameters:
            - write_off_id: WriteOffId.
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/write-offs/v1/{write_off_id}"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(WriteOff, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create(self, *, write_offs: typing.List[WriteOffCreate]) -> CreateWriteOffsResponse:
        """
        Creates one or many write-offs given a specific set of allocations.
        The allocations can describe whether the refund is being applied toward a specific service line,
        claim, or billing provider.

        Parameters:
            - write_offs: typing.List[WriteOffCreate].
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/write-offs/v1"),
            json=jsonable_encoder({"write_offs": write_offs}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(CreateWriteOffsResponse, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def revert(self, write_off_id: WriteOffId) -> WriteOff:
        """
        Reverts a write off given a `write_off_id`.

        Parameters:
            - write_off_id: WriteOffId.
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/write-offs/v1/{write_off_id}/revert"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(WriteOff, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def get_multi(
        self,
        *,
        limit: typing.Optional[int] = None,
        patient_external_id: typing.Optional[PatientExternalId] = None,
        payer_uuid: typing.Optional[PayerUuid] = None,
        service_line_id: typing.Optional[ServiceLineId] = None,
        claim_id: typing.Optional[ClaimId] = None,
        billing_provider_id: typing.Optional[ProviderId] = None,
        sort: typing.Optional[WriteOffSortField] = None,
        sort_direction: typing.Optional[SortDirection] = None,
        page_token: typing.Optional[PageToken] = None,
        account_types: typing.Optional[typing.Union[AccountType, typing.List[AccountType]]] = None,
    ) -> WriteOffsPage:
        """
        Returns all write-offs satisfying the search criteria.

        Parameters:
            - limit: typing.Optional[int]. Defaults to 100. The value must be greater than 0 and less than 1000.

            - patient_external_id: typing.Optional[PatientExternalId].

            - payer_uuid: typing.Optional[PayerUuid].

            - service_line_id: typing.Optional[ServiceLineId].

            - claim_id: typing.Optional[ClaimId].

            - billing_provider_id: typing.Optional[ProviderId].

            - sort: typing.Optional[WriteOffSortField]. Defaults to write_off_timestamp

            - sort_direction: typing.Optional[SortDirection]. Sort direction. Defaults to descending order if not provided.

            - page_token: typing.Optional[PageToken].

            - account_types: typing.Optional[typing.Union[AccountType, typing.List[AccountType]]]. Filters the returned values to include only the provided account types.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/write-offs/v1"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "patient_external_id": patient_external_id,
                    "payer_uuid": jsonable_encoder(payer_uuid),
                    "service_line_id": jsonable_encoder(service_line_id),
                    "claim_id": jsonable_encoder(claim_id),
                    "billing_provider_id": jsonable_encoder(billing_provider_id),
                    "sort": sort,
                    "sort_direction": sort_direction,
                    "page_token": page_token,
                    "account_types": account_types,
                }
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(WriteOffsPage, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(self, write_off_id: WriteOffId) -> WriteOff:
        """
        Retrieves a previously created write off by its `write_off_id`.

        Parameters:
            - write_off_id: WriteOffId.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/write-offs/v1/{write_off_id}"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(WriteOff, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create(self, *, write_offs: typing.List[WriteOffCreate]) -> CreateWriteOffsResponse:
        """
        Creates one or many write-offs given a specific set of allocations.
        The allocations can describe whether the refund is being applied toward a specific service line,
        claim, or billing provider.

        Parameters:
            - write_offs: typing.List[WriteOffCreate].
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/write-offs/v1"),
            json=jsonable_encoder({"write_offs": write_offs}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(CreateWriteOffsResponse, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def revert(self, write_off_id: WriteOffId) -> WriteOff:
        """
        Reverts a write off given a `write_off_id`.

        Parameters:
            - write_off_id: WriteOffId.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/write-offs/v1/{write_off_id}/revert"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(WriteOff, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)
