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

import datetime as dt
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.errors.entity_not_found_error import EntityNotFoundError
from ....commons.errors.unauthorized_error import UnauthorizedError
from ....commons.errors.unprocessable_entity_error import UnprocessableEntityError
from ....commons.types.claim_id import ClaimId
from ....commons.types.entity_not_found_error_message import EntityNotFoundErrorMessage
from ....commons.types.page_token import PageToken
from ....commons.types.provider_id import ProviderId
from ....commons.types.service_line_id import ServiceLineId
from ....commons.types.sort_direction import SortDirection
from ....commons.types.unauthorized_error_message import UnauthorizedErrorMessage
from ....commons.types.unprocessable_entity_error_message import UnprocessableEntityErrorMessage
from ....financials.types.note_update import NoteUpdate
from ....financials.types.refund_reason_update import RefundReasonUpdate
from ....payers.resources.v_3.types.payer_uuid import PayerUuid
from .types.insurance_refund import InsuranceRefund
from .types.insurance_refund_create import InsuranceRefundCreate
from .types.insurance_refund_id import InsuranceRefundId
from .types.insurance_refund_sort_field import InsuranceRefundSortField
from .types.insurance_refunds_page import InsuranceRefundsPage

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,
        payer_uuid: typing.Optional[PayerUuid] = None,
        claim_id: typing.Optional[ClaimId] = None,
        service_line_id: typing.Optional[ServiceLineId] = None,
        billing_provider_id: typing.Optional[ProviderId] = None,
        sort: typing.Optional[InsuranceRefundSortField] = None,
        sort_direction: typing.Optional[SortDirection] = None,
        page_token: typing.Optional[PageToken] = None,
    ) -> InsuranceRefundsPage:
        """
        Returns all insurance refunds satisfying the search criteria AND whose organization_id matches
        the current organization_id of the authenticated user.

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

            - payer_uuid: typing.Optional[PayerUuid].

            - claim_id: typing.Optional[ClaimId].

            - service_line_id: typing.Optional[ServiceLineId].

            - billing_provider_id: typing.Optional[ProviderId].

            - sort: typing.Optional[InsuranceRefundSortField]. Defaults to refund_timestamp

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

            - page_token: typing.Optional[PageToken].
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/insurance-refunds/v1"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "payer_uuid": jsonable_encoder(payer_uuid),
                    "claim_id": jsonable_encoder(claim_id),
                    "service_line_id": jsonable_encoder(service_line_id),
                    "billing_provider_id": jsonable_encoder(billing_provider_id),
                    "sort": sort,
                    "sort_direction": sort_direction,
                    "page_token": page_token,
                }
            ),
            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(InsuranceRefundsPage, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(self, insurance_refund_id: InsuranceRefundId) -> InsuranceRefund:
        """
        Retrieves a previously created insurance refund by its `insurance_refund_id`.
        If the refund does not exist, a `403` will be thrown.

        Parameters:
            - insurance_refund_id: InsuranceRefundId.
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"api/insurance-refunds/v1/{insurance_refund_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(InsuranceRefund, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create(self, *, request: InsuranceRefundCreate) -> InsuranceRefund:
        """
        Creates a new insurance refund record and returns the newly created `InsuranceRefund` object.
        The allocations can describe whether the refund is being applied toward a specific service line,
        claim, or billing provider.

        Parameters:
            - request: InsuranceRefundCreate.
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/insurance-refunds/v1"),
            json=jsonable_encoder(request),
            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(InsuranceRefund, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update(
        self,
        insurance_refund_id: InsuranceRefundId,
        *,
        refund_timestamp: typing.Optional[dt.datetime] = OMIT,
        refund_note: typing.Optional[NoteUpdate] = OMIT,
        refund_reason: typing.Optional[RefundReasonUpdate] = OMIT,
    ) -> InsuranceRefund:
        """
        Updates the patient refund record matching the provided insurance_refund_id. If updating the refund amount,
        then the allocations must be appropriately updated as well.

        Parameters:
            - insurance_refund_id: InsuranceRefundId.

            - refund_timestamp: typing.Optional[dt.datetime].

            - refund_note: typing.Optional[NoteUpdate].

            - refund_reason: typing.Optional[RefundReasonUpdate].
        """
        _request: typing.Dict[str, typing.Any] = {}
        if refund_timestamp is not OMIT:
            _request["refund_timestamp"] = refund_timestamp
        if refund_note is not OMIT:
            _request["refund_note"] = refund_note
        if refund_reason is not OMIT:
            _request["refund_reason"] = refund_reason
        _response = self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"api/insurance-refunds/v1/{insurance_refund_id}"
            ),
            json=jsonable_encoder(_request),
            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(InsuranceRefund, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete(self, insurance_refund_id: InsuranceRefundId) -> None:
        """
        Deletes the insurance refund record matching the provided `insurance_refund_id`.
        If the matching record's organization_id does not match the authenticated user's
        current organization_id, then a response code of `403` will be returned.

        Parameters:
            - insurance_refund_id: InsuranceRefundId.
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"api/insurance-refunds/v1/{insurance_refund_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # 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,
        payer_uuid: typing.Optional[PayerUuid] = None,
        claim_id: typing.Optional[ClaimId] = None,
        service_line_id: typing.Optional[ServiceLineId] = None,
        billing_provider_id: typing.Optional[ProviderId] = None,
        sort: typing.Optional[InsuranceRefundSortField] = None,
        sort_direction: typing.Optional[SortDirection] = None,
        page_token: typing.Optional[PageToken] = None,
    ) -> InsuranceRefundsPage:
        """
        Returns all insurance refunds satisfying the search criteria AND whose organization_id matches
        the current organization_id of the authenticated user.

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

            - payer_uuid: typing.Optional[PayerUuid].

            - claim_id: typing.Optional[ClaimId].

            - service_line_id: typing.Optional[ServiceLineId].

            - billing_provider_id: typing.Optional[ProviderId].

            - sort: typing.Optional[InsuranceRefundSortField]. Defaults to refund_timestamp

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

            - page_token: typing.Optional[PageToken].
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/insurance-refunds/v1"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "payer_uuid": jsonable_encoder(payer_uuid),
                    "claim_id": jsonable_encoder(claim_id),
                    "service_line_id": jsonable_encoder(service_line_id),
                    "billing_provider_id": jsonable_encoder(billing_provider_id),
                    "sort": sort,
                    "sort_direction": sort_direction,
                    "page_token": page_token,
                }
            ),
            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(InsuranceRefundsPage, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(self, insurance_refund_id: InsuranceRefundId) -> InsuranceRefund:
        """
        Retrieves a previously created insurance refund by its `insurance_refund_id`.
        If the refund does not exist, a `403` will be thrown.

        Parameters:
            - insurance_refund_id: InsuranceRefundId.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"api/insurance-refunds/v1/{insurance_refund_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(InsuranceRefund, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create(self, *, request: InsuranceRefundCreate) -> InsuranceRefund:
        """
        Creates a new insurance refund record and returns the newly created `InsuranceRefund` object.
        The allocations can describe whether the refund is being applied toward a specific service line,
        claim, or billing provider.

        Parameters:
            - request: InsuranceRefundCreate.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/insurance-refunds/v1"),
            json=jsonable_encoder(request),
            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(InsuranceRefund, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update(
        self,
        insurance_refund_id: InsuranceRefundId,
        *,
        refund_timestamp: typing.Optional[dt.datetime] = OMIT,
        refund_note: typing.Optional[NoteUpdate] = OMIT,
        refund_reason: typing.Optional[RefundReasonUpdate] = OMIT,
    ) -> InsuranceRefund:
        """
        Updates the patient refund record matching the provided insurance_refund_id. If updating the refund amount,
        then the allocations must be appropriately updated as well.

        Parameters:
            - insurance_refund_id: InsuranceRefundId.

            - refund_timestamp: typing.Optional[dt.datetime].

            - refund_note: typing.Optional[NoteUpdate].

            - refund_reason: typing.Optional[RefundReasonUpdate].
        """
        _request: typing.Dict[str, typing.Any] = {}
        if refund_timestamp is not OMIT:
            _request["refund_timestamp"] = refund_timestamp
        if refund_note is not OMIT:
            _request["refund_note"] = refund_note
        if refund_reason is not OMIT:
            _request["refund_reason"] = refund_reason
        _response = await self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"api/insurance-refunds/v1/{insurance_refund_id}"
            ),
            json=jsonable_encoder(_request),
            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(InsuranceRefund, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete(self, insurance_refund_id: InsuranceRefundId) -> None:
        """
        Deletes the insurance refund record matching the provided `insurance_refund_id`.
        If the matching record's organization_id does not match the authenticated user's
        current organization_id, then a response code of `403` will be returned.

        Parameters:
            - insurance_refund_id: InsuranceRefundId.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", f"api/insurance-refunds/v1/{insurance_refund_id}"
            ),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnauthorizedError":
                raise UnauthorizedError(
                    pydantic.parse_obj_as(UnauthorizedErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "UnprocessableEntityError":
                raise UnprocessableEntityError(
                    pydantic.parse_obj_as(UnprocessableEntityErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)
