# 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.datetime_utils import serialize_datetime
from .....core.jsonable_encoder import jsonable_encoder
from .....core.remove_none_from_dict import remove_none_from_dict
from ....billing_notes.resources.v_2.types.billing_note_base import BillingNoteBase
from ....claim_submission.resources.v_1.types.external_claim_submission_create import ExternalClaimSubmissionCreate
from ....claims.types.claim_status import ClaimStatus
from ....commons.errors.entity_not_found_error import EntityNotFoundError
from ....commons.errors.http_request_validations_error import HttpRequestValidationsError
from ....commons.errors.unauthorized_error import UnauthorizedError
from ....commons.types.date import Date
from ....commons.types.delay_reason_code import DelayReasonCode
from ....commons.types.encounter_external_id import EncounterExternalId
from ....commons.types.encounter_id import EncounterId
from ....commons.types.entity_not_found_error_message import EntityNotFoundErrorMessage
from ....commons.types.facility_type_code import FacilityTypeCode
from ....commons.types.page_token import PageToken
from ....commons.types.request_validation_error import RequestValidationError
from ....commons.types.street_address_long_zip import StreetAddressLongZip
from ....commons.types.unauthorized_error_message import UnauthorizedErrorMessage
from ....commons.types.work_queue_id import WorkQueueId
from ....diagnoses.types.diagnosis_create import DiagnosisCreate
from ....diagnoses.types.diagnosis_id import DiagnosisId
from ....encounter_providers.resources.v_2.types.billing_provider import BillingProvider
from ....encounter_providers.resources.v_2.types.referring_provider import ReferringProvider
from ....encounter_providers.resources.v_2.types.rendering_provider import RenderingProvider
from ....guarantor.resources.v_1.types.guarantor_create import GuarantorCreate
from ....individual.types.patient_create import PatientCreate
from ....individual.types.subscriber_create import SubscriberCreate
from ....service_facility.types.encounter_service_facility_base import EncounterServiceFacilityBase
from ....service_lines.resources.v_2.types.service_line_create import ServiceLineCreate
from ....tags.types.tag_id import TagId
from .errors.cash_pay_payer_error import CashPayPayerError
from .errors.encounter_external_id_uniqueness_error import EncounterExternalIdUniquenessError
from .errors.encounter_guarantor_missing_contact_info_error import EncounterGuarantorMissingContactInfoError
from .errors.encounter_patient_control_number_uniqueness_error import EncounterPatientControlNumberUniquenessError
from .types.billable_status_type import BillableStatusType
from .types.cash_pay_payer_error_message import CashPayPayerErrorMessage
from .types.clinical_note_category_create import ClinicalNoteCategoryCreate
from .types.encounter import Encounter
from .types.encounter_external_id_uniqueness_error_type import EncounterExternalIdUniquenessErrorType
from .types.encounter_guarantor_missing_contact_info_error_type import EncounterGuarantorMissingContactInfoErrorType
from .types.encounter_owner_of_next_action_type import EncounterOwnerOfNextActionType
from .types.encounter_page import EncounterPage
from .types.encounter_patient_control_number_uniqueness_error_type import (
    EncounterPatientControlNumberUniquenessErrorType,
)
from .types.encounter_sort_options import EncounterSortOptions
from .types.intervention import Intervention
from .types.medication import Medication
from .types.patient_history_category import PatientHistoryCategory
from .types.prior_authorization_number import PriorAuthorizationNumber
from .types.responsible_party_type import ResponsiblePartyType
from .types.service_authorization_exception_code import ServiceAuthorizationExceptionCode
from .types.synchronicity_type import SynchronicityType
from .types.vitals import Vitals

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 V4Client:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def get_all(
        self,
        *,
        limit: typing.Optional[int] = None,
        claim_status: typing.Optional[ClaimStatus] = None,
        sort: typing.Optional[EncounterSortOptions] = None,
        page_token: typing.Optional[PageToken] = None,
        date_of_service_min: typing.Optional[Date] = None,
        date_of_service_max: typing.Optional[Date] = None,
        primary_payer_names: typing.Optional[str] = None,
        search_term: typing.Optional[str] = None,
        external_id: typing.Optional[EncounterExternalId] = None,
        diagnoses_updated_since: typing.Optional[dt.datetime] = None,
        tag_ids: typing.Optional[typing.Union[TagId, typing.List[TagId]]] = None,
        work_queue_id: typing.Optional[WorkQueueId] = None,
        billable_status: typing.Optional[BillableStatusType] = None,
        responsible_party: typing.Optional[ResponsiblePartyType] = None,
        owner_of_next_action: typing.Optional[EncounterOwnerOfNextActionType] = None,
    ) -> EncounterPage:
        """
        Parameters:
            - limit: typing.Optional[int]. Maximum number of entities per page, defaults to 100.

            - claim_status: typing.Optional[ClaimStatus]. Indicates the current status of an insurance claim within the billing process.

            - sort: typing.Optional[EncounterSortOptions]. Defaults to created_at:desc.

            - page_token: typing.Optional[PageToken].

            - date_of_service_min: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.

            - date_of_service_max: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.

            - primary_payer_names: typing.Optional[str]. Comma delimited string.

            - search_term: typing.Optional[str]. Filter by any of the following fields: encounter_id, claim_id, patient external_id,
                                                 patient date of birth, patient first name, patient last name,
                                                 or encounter external id.
            - external_id: typing.Optional[EncounterExternalId]. Filter to an exact match on encounter external_id, if one exists.

            - diagnoses_updated_since: typing.Optional[dt.datetime]. ISO 8601 timestamp; ideally in UTC (although not required): 2019-08-24T14:15:22Z.

            - tag_ids: typing.Optional[typing.Union[TagId, typing.List[TagId]]]. Filter by name of tags on encounters.

            - work_queue_id: typing.Optional[WorkQueueId].

            - billable_status: typing.Optional[BillableStatusType]. Defines if the Encounter is to be billed by Candid to the responsible_party. Examples for when this should be set to NOT_BILLABLE include if the Encounter has not occurred yet or if there is no intention of ever billing the responsible_party.

            - responsible_party: typing.Optional[ResponsiblePartyType]. Defines the party to be billed with the initial balance owed on the claim. Use SELF_PAY if you intend to bill self pay/cash pay.

            - owner_of_next_action: typing.Optional[EncounterOwnerOfNextActionType]. The party who is responsible for taking the next action on an Encounter, as defined by ownership of open Tasks.
        ---
        import datetime

        from candid import ClaimStatus
        from candid.client import CandidApi
        from candid.resources.encounters.v_4 import EncounterSortOptions

        client = CandidApi(
            token="YOUR_TOKEN",
        )
        client.encounters.v_4.get_all(
            limit=100,
            claim_status=ClaimStatus.BILLER_RECEIVED,
            sort=EncounterSortOptions.CREATED_AT_ASC,
            page_token="eyJ0b2tlbiI6IjEiLCJwYWdlX3Rva2VuIjoiMiJ9",
            date_of_service_min="2019-08-24",
            date_of_service_max="2019-08-25",
            primary_payer_names="Medicare,Medicaid",
            search_term="doe",
            external_id="123456",
            diagnoses_updated_since=datetime.datetime.fromisoformat(
                "2019-08-24 14:15:22+00:00",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/encounters/v4"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "claim_status": claim_status,
                    "sort": sort,
                    "page_token": page_token,
                    "date_of_service_min": date_of_service_min,
                    "date_of_service_max": date_of_service_max,
                    "primary_payer_names": primary_payer_names,
                    "search_term": search_term,
                    "external_id": external_id,
                    "diagnoses_updated_since": serialize_datetime(diagnoses_updated_since)
                    if diagnoses_updated_since is not None
                    else None,
                    "tag_ids": tag_ids,
                    "work_queue_id": work_queue_id,
                    "billable_status": billable_status,
                    "responsible_party": responsible_party,
                    "owner_of_next_action": owner_of_next_action,
                }
            ),
            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(EncounterPage, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(self, encounter_id: EncounterId) -> Encounter:
        """
        Parameters:
            - encounter_id: EncounterId.
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/encounters/v4/{encounter_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(Encounter, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create(
        self,
        *,
        patient: PatientCreate,
        billing_provider: BillingProvider,
        rendering_provider: RenderingProvider,
        referring_provider: typing.Optional[ReferringProvider] = OMIT,
        service_facility: typing.Optional[EncounterServiceFacilityBase] = OMIT,
        subscriber_primary: typing.Optional[SubscriberCreate] = OMIT,
        subscriber_secondary: typing.Optional[SubscriberCreate] = OMIT,
        diagnoses: typing.List[DiagnosisCreate],
        clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]] = OMIT,
        billing_notes: typing.Optional[typing.List[BillingNoteBase]] = OMIT,
        place_of_service_code: FacilityTypeCode,
        patient_histories: typing.Optional[typing.List[PatientHistoryCategory]] = OMIT,
        service_lines: typing.Optional[typing.List[ServiceLineCreate]] = OMIT,
        guarantor: typing.Optional[GuarantorCreate] = OMIT,
        external_claim_submission: typing.Optional[ExternalClaimSubmissionCreate] = OMIT,
        external_id: EncounterExternalId,
        date_of_service: Date,
        end_date_of_service: typing.Optional[Date] = OMIT,
        prior_authorization_number: typing.Optional[PriorAuthorizationNumber] = OMIT,
        patient_authorized_release: bool,
        benefits_assigned_to_provider: bool,
        provider_accepts_assignment: bool,
        appointment_type: typing.Optional[str] = OMIT,
        existing_medications: typing.Optional[typing.List[Medication]] = OMIT,
        vitals: typing.Optional[Vitals] = OMIT,
        interventions: typing.Optional[typing.List[Intervention]] = OMIT,
        pay_to_address: typing.Optional[StreetAddressLongZip] = OMIT,
        synchronicity: typing.Optional[SynchronicityType] = OMIT,
        billable_status: BillableStatusType,
        responsible_party: ResponsiblePartyType,
        additional_information: typing.Optional[str] = OMIT,
        service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode] = OMIT,
        admission_date: typing.Optional[Date] = OMIT,
        discharge_date: typing.Optional[Date] = OMIT,
        onset_of_current_illness_or_symptom_date: typing.Optional[Date] = OMIT,
        last_menstrual_period_date: typing.Optional[Date] = OMIT,
        delay_reason_code: typing.Optional[DelayReasonCode] = OMIT,
    ) -> Encounter:
        """
        Parameters:
            - patient: PatientCreate. Contains the identification information of the individual receiving medical services.

            - billing_provider: BillingProvider. The billing provider is the provider or business entity submitting the claim. Billing provider may be, but is not necessarily, the same person/NPI as the rendering provider. From a payer's perspective, this represents the person or entity being reimbursed. When a contract exists with the target payer, the billing provider should be the entity contracted with the payer. In some circumstances, this will be an individual provider. In that case, submit that provider's NPI and the tax ID (TIN) that the provider gave to the payer during contracting. In other cases, the billing entity will be a medical group. If so, submit the group NPI and the group's tax ID. Box 33 on the CMS-1500 claim form.

            - rendering_provider: RenderingProvider. The rendering provider is the practitioner -- physician, nurse practitioner, etc. -- performing the service.
                                                     For telehealth services, the rendering provider performs the visit, asynchronous communication, or other service. The rendering provider address should generally be the same as the service facility address.

            - referring_provider: typing.Optional[ReferringProvider]. The provider who referred the services that were rendered.
                                                                      All physicians who order services or refer Medicare beneficiaries must
                                                                      report this data.
                                                                      If a claim involves multiple referring physicians, create a separate
                                                                      encounter for each physician.

            - service_facility: typing.Optional[EncounterServiceFacilityBase]. Encounter Service facility is typically the location a medical service was rendered, such as a provider office or hospital. For telehealth, service facility can represent the provider's location when the service was delivered (e.g., home), or the location where an in-person visit would have taken place, whichever is easier to identify. If the provider is in-network, service facility may be defined in payer contracts. Box 32 on the CMS-1500 claim form. Note that for an in-network claim to be successfully adjudicated, the service facility address listed on claims must match what was provided to the payer during the credentialing process.

            - subscriber_primary: typing.Optional[SubscriberCreate]. Subscriber_primary is required when responsible_party is INSURANCE_PAY (i.e. when the claim should be billed to insurance).
                                                                     These are not required fields when responsible_party is SELF_PAY (i.e. when the claim should be billed to the patient).
                                                                     However, if you collect this for patients, even self-pay, we recommend including it when sending encounters to Candid.
                                                                     Note: Cash Pay is no longer a valid payer_id in v4, please use responsible party to define self-pay claims.

            - subscriber_secondary: typing.Optional[SubscriberCreate]. Please always include this when you have it, even for self-pay claims.

            - diagnoses: typing.List[DiagnosisCreate]. Ideally, this field should contain no more than 12 diagnoses. However, more diagnoses
                                                       may be submitted at this time, and coders will later prioritize the 12 that will be
                                                       submitted to the payor.

            - clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]]. Holds a collection of clinical observations made by healthcare providers during patient encounters.

            - billing_notes: typing.Optional[typing.List[BillingNoteBase]]. Spot to store misc, human-readable, notes about this encounter to be used
                                                                            in the billing process.

            - place_of_service_code: FacilityTypeCode. Box 24B on the CMS-1500 claim form. Line-level place of service is not currently supported. 02 for telemedicine, 11 for in-person. Full list [here](https://www.cms.gov/Medicare/Coding/place-of-service-codes/Place_of_Service_Code_Set).

            - patient_histories: typing.Optional[typing.List[PatientHistoryCategory]].

            - service_lines: typing.Optional[typing.List[ServiceLineCreate]]. Each service line must be linked to a diagnosis. Concretely,
                                                                              `service_line.diagnosis_pointers`must contain at least one entry which should be
                                                                              in bounds of the diagnoses list field.

            - guarantor: typing.Optional[GuarantorCreate]. Personal and contact info for the guarantor of the patient responsibility.

            - external_claim_submission: typing.Optional[ExternalClaimSubmissionCreate]. ***This field is in beta.***
                                                                                         To be included for claims that have been submitted outside of Candid.
                                                                                         Candid supports posting remits and payments to these claims and working them in-platform (e.g. editing, resubmitting).

            - external_id: EncounterExternalId. A client-specified unique ID to associate with this encounter;
                                                for example, your internal encounter ID or a Dr. Chrono encounter ID.
                                                This field should not contain PHI.
            - date_of_service: Date. Date formatted as YYYY-MM-DD; eg: 2019-08-24.
                                     This date must be the local date in the timezone where the service occurred.
                                     Box 24a on the CMS-1500 claim form.
                                     If service occurred over a range of dates, this should be the start date.
            - end_date_of_service: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.
                                                          This date must be the local date in the timezone where the service occurred.
                                                          If omitted, the Encounter is assumed to be for a single day.
                                                          Must not be temporally before the date_of_service field.
            - prior_authorization_number: typing.Optional[PriorAuthorizationNumber]. Box 23 on the CMS-1500 claim form.

            - patient_authorized_release: bool. Whether this patient has authorized the release of medical information
                                                for billing purpose.
                                                Box 12 on the CMS-1500 claim form.
            - benefits_assigned_to_provider: bool. Whether this patient has authorized insurance payments to be made to you,
                                                   not them. If false, patient may receive reimbursement.
                                                   Box 13 on the CMS-1500 claim form.
            - provider_accepts_assignment: bool. Whether you have accepted the patient's authorization for insurance payments
                                                 to be made to you, not them.
                                                 Box 27 on the CMS-1500 claim form.
            - appointment_type: typing.Optional[str]. Human-readable description of the appointment type (ex: "Acupuncture - Headaches").

            - existing_medications: typing.Optional[typing.List[Medication]].

            - vitals: typing.Optional[Vitals].

            - interventions: typing.Optional[typing.List[Intervention]].

            - pay_to_address: typing.Optional[StreetAddressLongZip]. Specifies the address to which payments for the claim should be sent.

            - synchronicity: typing.Optional[SynchronicityType]. Whether or not this was a synchronous or asynchronous encounter.
                                                                 Asynchronous encounters occur when providers and patients communicate online using
                                                                 forms, instant messaging, or other pre-recorded digital mediums.
                                                                 Synchronous encounters occur in live, real-time settings where the patient interacts
                                                                 directly with the provider, such as over video or a phone call.
            - billable_status: BillableStatusType. Defines if the Encounter is to be billed by Candid to the responsible_party.
                                                   Examples for when this should be set to NOT_BILLABLE include
                                                   if the Encounter has not occurred yet or if there is no intention of ever billing the responsible_party.
            - responsible_party: ResponsiblePartyType. Defines the party to be billed with the initial balance owed on the claim.

            - additional_information: typing.Optional[str]. Defines additional information on the claim needed by the payer.
                                                            Box 19 on the CMS-1500 claim form.
            - service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode]. 837p Loop2300 REF\*4N
                                                                                                        Required when mandated by government law or regulation to obtain authorization for specific service(s) but, for the
                                                                                                        reasons listed in one of the enum values of ServiceAuthorizationExceptionCode, the service was performed without
                                                                                                        obtaining the authorization.
            - admission_date: typing.Optional[Date]. 837p Loop2300 DTP\*435, CMS-1500 Box 18
                                                     Required on all ambulance claims when the patient was known to be admitted to the hospital.
                                                     OR
                                                     Required on all claims involving inpatient medical visits.
            - discharge_date: typing.Optional[Date]. 837p Loop2300 DTP\*096, CMS-1500 Box 18
                                                     Required for inpatient claims when the patient was discharged from the facility and the discharge date is known.
            - onset_of_current_illness_or_symptom_date: typing.Optional[Date]. 837p Loop2300 DTP\*431, CMS-1500 Box 14
                                                                               Required for the initial medical service or visit performed in response to a medical emergency when the date is available and is different than the date of service.
                                                                               OR
                                                                               This date is the onset of acute symptoms for the current illness or condition.
            - last_menstrual_period_date: typing.Optional[Date]. 837p Loop2300 DTP\*484, CMS-1500 Box 14
                                                                 Required when, in the judgment of the provider, the services on this claim are related to the patient's pregnancy.
            - delay_reason_code: typing.Optional[DelayReasonCode]. 837i Loop2300, CLM-1300 Box 20
                                                                   Code indicating the reason why a request was delayed
        """
        _request: typing.Dict[str, typing.Any] = {
            "patient": patient,
            "billing_provider": billing_provider,
            "rendering_provider": rendering_provider,
            "diagnoses": diagnoses,
            "place_of_service_code": place_of_service_code,
            "external_id": external_id,
            "date_of_service": date_of_service,
            "patient_authorized_release": patient_authorized_release,
            "benefits_assigned_to_provider": benefits_assigned_to_provider,
            "provider_accepts_assignment": provider_accepts_assignment,
            "billable_status": billable_status,
            "responsible_party": responsible_party,
        }
        if referring_provider is not OMIT:
            _request["referring_provider"] = referring_provider
        if service_facility is not OMIT:
            _request["service_facility"] = service_facility
        if subscriber_primary is not OMIT:
            _request["subscriber_primary"] = subscriber_primary
        if subscriber_secondary is not OMIT:
            _request["subscriber_secondary"] = subscriber_secondary
        if clinical_notes is not OMIT:
            _request["clinical_notes"] = clinical_notes
        if billing_notes is not OMIT:
            _request["billing_notes"] = billing_notes
        if patient_histories is not OMIT:
            _request["patient_histories"] = patient_histories
        if service_lines is not OMIT:
            _request["service_lines"] = service_lines
        if guarantor is not OMIT:
            _request["guarantor"] = guarantor
        if external_claim_submission is not OMIT:
            _request["external_claim_submission"] = external_claim_submission
        if end_date_of_service is not OMIT:
            _request["end_date_of_service"] = end_date_of_service
        if prior_authorization_number is not OMIT:
            _request["prior_authorization_number"] = prior_authorization_number
        if appointment_type is not OMIT:
            _request["appointment_type"] = appointment_type
        if existing_medications is not OMIT:
            _request["existing_medications"] = existing_medications
        if vitals is not OMIT:
            _request["vitals"] = vitals
        if interventions is not OMIT:
            _request["interventions"] = interventions
        if pay_to_address is not OMIT:
            _request["pay_to_address"] = pay_to_address
        if synchronicity is not OMIT:
            _request["synchronicity"] = synchronicity
        if additional_information is not OMIT:
            _request["additional_information"] = additional_information
        if service_authorization_exception_code is not OMIT:
            _request["service_authorization_exception_code"] = service_authorization_exception_code
        if admission_date is not OMIT:
            _request["admission_date"] = admission_date
        if discharge_date is not OMIT:
            _request["discharge_date"] = discharge_date
        if onset_of_current_illness_or_symptom_date is not OMIT:
            _request["onset_of_current_illness_or_symptom_date"] = onset_of_current_illness_or_symptom_date
        if last_menstrual_period_date is not OMIT:
            _request["last_menstrual_period_date"] = last_menstrual_period_date
        if delay_reason_code is not OMIT:
            _request["delay_reason_code"] = delay_reason_code
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/encounters/v4"),
            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(Encounter, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EncounterExternalIdUniquenessError":
                raise EncounterExternalIdUniquenessError(
                    pydantic.parse_obj_as(EncounterExternalIdUniquenessErrorType, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "EncounterPatientControlNumberUniquenessError":
                raise EncounterPatientControlNumberUniquenessError(
                    pydantic.parse_obj_as(EncounterPatientControlNumberUniquenessErrorType, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "EncounterGuarantorMissingContactInfoError":
                raise EncounterGuarantorMissingContactInfoError(
                    pydantic.parse_obj_as(EncounterGuarantorMissingContactInfoErrorType, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "HttpRequestValidationsError":
                raise HttpRequestValidationsError(
                    pydantic.parse_obj_as(typing.List[RequestValidationError], _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "CashPayPayerError":
                raise CashPayPayerError(
                    pydantic.parse_obj_as(CashPayPayerErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update(
        self,
        encounter_id: EncounterId,
        *,
        prior_authorization_number: typing.Optional[PriorAuthorizationNumber] = OMIT,
        external_id: typing.Optional[EncounterExternalId] = OMIT,
        date_of_service: typing.Optional[Date] = OMIT,
        diagnosis_ids: typing.Optional[typing.List[DiagnosisId]] = OMIT,
        tag_ids: typing.Optional[typing.List[TagId]] = OMIT,
        clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]] = OMIT,
        pay_to_address: typing.Optional[StreetAddressLongZip] = OMIT,
        billable_status: typing.Optional[BillableStatusType] = OMIT,
        responsible_party: typing.Optional[ResponsiblePartyType] = OMIT,
        provider_accepts_assignment: typing.Optional[bool] = OMIT,
        benefits_assigned_to_provider: typing.Optional[bool] = OMIT,
        synchronicity: typing.Optional[SynchronicityType] = OMIT,
        place_of_service_code: typing.Optional[FacilityTypeCode] = OMIT,
        appointment_type: typing.Optional[str] = OMIT,
        end_date_of_service: typing.Optional[Date] = OMIT,
        subscriber_primary: typing.Optional[SubscriberCreate] = OMIT,
        subscriber_secondary: typing.Optional[SubscriberCreate] = OMIT,
        additional_information: typing.Optional[str] = OMIT,
        service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode] = OMIT,
        admission_date: typing.Optional[Date] = OMIT,
        discharge_date: typing.Optional[Date] = OMIT,
        onset_of_current_illness_or_symptom_date: typing.Optional[Date] = OMIT,
        last_menstrual_period_date: typing.Optional[Date] = OMIT,
        delay_reason_code: typing.Optional[DelayReasonCode] = OMIT,
    ) -> Encounter:
        """
        Parameters:
            - encounter_id: EncounterId.

            - prior_authorization_number: typing.Optional[PriorAuthorizationNumber]. Box 23 on the CMS-1500 claim form.

            - external_id: typing.Optional[EncounterExternalId]. A client-specified unique ID to associate with this encounter;
                                                                 for example, your internal encounter ID or a Dr. Chrono encounter ID.
                                                                 This field should not contain PHI.

            - date_of_service: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-24.
                                                      This date must be the local date in the timezone where the service occurred.
                                                      Box 24a on the CMS-1500 claim form.
                                                      If service occurred over a range of dates, this should be the start date.

            - diagnosis_ids: typing.Optional[typing.List[DiagnosisId]]. Ideally, this field should contain no more than 12 diagnoses. However, more diagnoses
                                                                        may be submitted at this time, and coders will later prioritize the 12 that will be
                                                                        submitted to the payor.

            - tag_ids: typing.Optional[typing.List[TagId]]. Names of tags that should be on the encounter.

            - clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]]. Holds a collection of clinical observations made by healthcare providers during patient encounters.

            - pay_to_address: typing.Optional[StreetAddressLongZip]. Specifies the address to which payments for the claim should be sent.

            - billable_status: typing.Optional[BillableStatusType]. Defines if the Encounter is to be billed by Candid to the responsible_party. Examples for when this should be set to NOT_BILLABLE include if the Encounter has not occurred yet or if there is no intention of ever billing the responsible_party.

            - responsible_party: typing.Optional[ResponsiblePartyType]. Defines the party to be billed with the initial balance owed on the claim. Use SELF_PAY if you intend to bill self pay/cash pay.

            - provider_accepts_assignment: typing.Optional[bool]. Whether you have accepted the patient's authorization for insurance payments to be made to you, not them. Box 27 on the CMS-1500 claim form.

            - benefits_assigned_to_provider: typing.Optional[bool]. Whether this patient has authorized insurance payments to be made to you, not them. If false, patient may receive reimbursement. Box 13 on the CMS-1500 claim form.

            - synchronicity: typing.Optional[SynchronicityType]. Whether or not this was a synchronous or asynchronous encounter. Asynchronous encounters occur when providers and patients communicate online using forms, instant messaging, or other pre-recorded digital mediums. Synchronous encounters occur in live, real-time settings where the patient interacts directly with the provider, such as over video or a phone call.

            - place_of_service_code: typing.Optional[FacilityTypeCode]. Box 24B on the CMS-1500 claim form. Line-level place of service is not currently supported. 02 for telemedicine, 11 for in-person. Full list [here](https://www.cms.gov/Medicare/Coding/place-of-service-codes/Place_of_Service_Code_Set).

            - appointment_type: typing.Optional[str]. Human-readable description of the appointment type (ex: "Acupuncture - Headaches").

            - end_date_of_service: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.
                                                          This date must be the local date in the timezone where the service occurred.
                                                          If omitted, the Encounter is assumed to be for a single day.
                                                          Must not be temporally before the date_of_service field.

            - subscriber_primary: typing.Optional[SubscriberCreate]. Contains details of the primary insurance subscriber.

            - subscriber_secondary: typing.Optional[SubscriberCreate]. Contains details of the secondary insurance subscriber.

            - additional_information: typing.Optional[str]. Defines additional information on the claim needed by the payer.
                                                            Box 19 on the CMS-1500 claim form.

            - service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode]. 837p Loop2300 REF*4N
                                                                                                        Required when mandated by government law or regulation to obtain authorization for specific service(s) but, for the
                                                                                                        reasons listed in one of the enum values of ServiceAuthorizationExceptionCode, the service was performed without
                                                                                                        obtaining the authorization.

            - admission_date: typing.Optional[Date]. 837p Loop2300 DTP*435, CMS-1500 Box 18
                                                     Required on all ambulance claims when the patient was known to be admitted to the hospital.
                                                     OR
                                                     Required on all claims involving inpatient medical visits.

            - discharge_date: typing.Optional[Date]. 837p Loop2300 DTP*096, CMS-1500 Box 18
                                                     Required for inpatient claims when the patient was discharged from the facility and the discharge date is known.

            - onset_of_current_illness_or_symptom_date: typing.Optional[Date]. 837p Loop2300 DTP*431, CMS-1500 Box 14
                                                                               Required for the initial medical service or visit performed in response to a medical emergency when the date is available and is different than the date of service.
                                                                               OR
                                                                               This date is the onset of acute symptoms for the current illness or condition.

            - last_menstrual_period_date: typing.Optional[Date]. 837p Loop2300 DTP*484, CMS-1500 Box 14
                                                                 Required when, in the judgment of the provider, the services on this claim are related to the patient's pregnancy.

            - delay_reason_code: typing.Optional[DelayReasonCode]. 837i Loop2300, CLM-1300 Box 20
                                                                   Code indicating the reason why a request was delayed

        """
        _request: typing.Dict[str, typing.Any] = {}
        if prior_authorization_number is not OMIT:
            _request["prior_authorization_number"] = prior_authorization_number
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if date_of_service is not OMIT:
            _request["date_of_service"] = date_of_service
        if diagnosis_ids is not OMIT:
            _request["diagnosis_ids"] = diagnosis_ids
        if tag_ids is not OMIT:
            _request["tag_ids"] = tag_ids
        if clinical_notes is not OMIT:
            _request["clinical_notes"] = clinical_notes
        if pay_to_address is not OMIT:
            _request["pay_to_address"] = pay_to_address
        if billable_status is not OMIT:
            _request["billable_status"] = billable_status
        if responsible_party is not OMIT:
            _request["responsible_party"] = responsible_party
        if provider_accepts_assignment is not OMIT:
            _request["provider_accepts_assignment"] = provider_accepts_assignment
        if benefits_assigned_to_provider is not OMIT:
            _request["benefits_assigned_to_provider"] = benefits_assigned_to_provider
        if synchronicity is not OMIT:
            _request["synchronicity"] = synchronicity
        if place_of_service_code is not OMIT:
            _request["place_of_service_code"] = place_of_service_code
        if appointment_type is not OMIT:
            _request["appointment_type"] = appointment_type
        if end_date_of_service is not OMIT:
            _request["end_date_of_service"] = end_date_of_service
        if subscriber_primary is not OMIT:
            _request["subscriber_primary"] = subscriber_primary
        if subscriber_secondary is not OMIT:
            _request["subscriber_secondary"] = subscriber_secondary
        if additional_information is not OMIT:
            _request["additional_information"] = additional_information
        if service_authorization_exception_code is not OMIT:
            _request["service_authorization_exception_code"] = service_authorization_exception_code
        if admission_date is not OMIT:
            _request["admission_date"] = admission_date
        if discharge_date is not OMIT:
            _request["discharge_date"] = discharge_date
        if onset_of_current_illness_or_symptom_date is not OMIT:
            _request["onset_of_current_illness_or_symptom_date"] = onset_of_current_illness_or_symptom_date
        if last_menstrual_period_date is not OMIT:
            _request["last_menstrual_period_date"] = last_menstrual_period_date
        if delay_reason_code is not OMIT:
            _request["delay_reason_code"] = delay_reason_code
        _response = self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/encounters/v4/{encounter_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(Encounter, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EncounterExternalIdUniquenessError":
                raise EncounterExternalIdUniquenessError(
                    pydantic.parse_obj_as(EncounterExternalIdUniquenessErrorType, _response_json["content"])  # type: ignore
                )
            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"] == "HttpRequestValidationsError":
                raise HttpRequestValidationsError(
                    pydantic.parse_obj_as(typing.List[RequestValidationError], _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def get_all(
        self,
        *,
        limit: typing.Optional[int] = None,
        claim_status: typing.Optional[ClaimStatus] = None,
        sort: typing.Optional[EncounterSortOptions] = None,
        page_token: typing.Optional[PageToken] = None,
        date_of_service_min: typing.Optional[Date] = None,
        date_of_service_max: typing.Optional[Date] = None,
        primary_payer_names: typing.Optional[str] = None,
        search_term: typing.Optional[str] = None,
        external_id: typing.Optional[EncounterExternalId] = None,
        diagnoses_updated_since: typing.Optional[dt.datetime] = None,
        tag_ids: typing.Optional[typing.Union[TagId, typing.List[TagId]]] = None,
        work_queue_id: typing.Optional[WorkQueueId] = None,
        billable_status: typing.Optional[BillableStatusType] = None,
        responsible_party: typing.Optional[ResponsiblePartyType] = None,
        owner_of_next_action: typing.Optional[EncounterOwnerOfNextActionType] = None,
    ) -> EncounterPage:
        """
        Parameters:
            - limit: typing.Optional[int]. Maximum number of entities per page, defaults to 100.

            - claim_status: typing.Optional[ClaimStatus]. Indicates the current status of an insurance claim within the billing process.

            - sort: typing.Optional[EncounterSortOptions]. Defaults to created_at:desc.

            - page_token: typing.Optional[PageToken].

            - date_of_service_min: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.

            - date_of_service_max: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.

            - primary_payer_names: typing.Optional[str]. Comma delimited string.

            - search_term: typing.Optional[str]. Filter by any of the following fields: encounter_id, claim_id, patient external_id,
                                                 patient date of birth, patient first name, patient last name,
                                                 or encounter external id.
            - external_id: typing.Optional[EncounterExternalId]. Filter to an exact match on encounter external_id, if one exists.

            - diagnoses_updated_since: typing.Optional[dt.datetime]. ISO 8601 timestamp; ideally in UTC (although not required): 2019-08-24T14:15:22Z.

            - tag_ids: typing.Optional[typing.Union[TagId, typing.List[TagId]]]. Filter by name of tags on encounters.

            - work_queue_id: typing.Optional[WorkQueueId].

            - billable_status: typing.Optional[BillableStatusType]. Defines if the Encounter is to be billed by Candid to the responsible_party. Examples for when this should be set to NOT_BILLABLE include if the Encounter has not occurred yet or if there is no intention of ever billing the responsible_party.

            - responsible_party: typing.Optional[ResponsiblePartyType]. Defines the party to be billed with the initial balance owed on the claim. Use SELF_PAY if you intend to bill self pay/cash pay.

            - owner_of_next_action: typing.Optional[EncounterOwnerOfNextActionType]. The party who is responsible for taking the next action on an Encounter, as defined by ownership of open Tasks.
        ---
        import datetime

        from candid import ClaimStatus
        from candid.client import AsyncCandidApi
        from candid.resources.encounters.v_4 import EncounterSortOptions

        client = AsyncCandidApi(
            token="YOUR_TOKEN",
        )
        await client.encounters.v_4.get_all(
            limit=100,
            claim_status=ClaimStatus.BILLER_RECEIVED,
            sort=EncounterSortOptions.CREATED_AT_ASC,
            page_token="eyJ0b2tlbiI6IjEiLCJwYWdlX3Rva2VuIjoiMiJ9",
            date_of_service_min="2019-08-24",
            date_of_service_max="2019-08-25",
            primary_payer_names="Medicare,Medicaid",
            search_term="doe",
            external_id="123456",
            diagnoses_updated_since=datetime.datetime.fromisoformat(
                "2019-08-24 14:15:22+00:00",
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/encounters/v4"),
            params=remove_none_from_dict(
                {
                    "limit": limit,
                    "claim_status": claim_status,
                    "sort": sort,
                    "page_token": page_token,
                    "date_of_service_min": date_of_service_min,
                    "date_of_service_max": date_of_service_max,
                    "primary_payer_names": primary_payer_names,
                    "search_term": search_term,
                    "external_id": external_id,
                    "diagnoses_updated_since": serialize_datetime(diagnoses_updated_since)
                    if diagnoses_updated_since is not None
                    else None,
                    "tag_ids": tag_ids,
                    "work_queue_id": work_queue_id,
                    "billable_status": billable_status,
                    "responsible_party": responsible_party,
                    "owner_of_next_action": owner_of_next_action,
                }
            ),
            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(EncounterPage, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(self, encounter_id: EncounterId) -> Encounter:
        """
        Parameters:
            - encounter_id: EncounterId.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/encounters/v4/{encounter_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(Encounter, _response_json)  # type: ignore
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create(
        self,
        *,
        patient: PatientCreate,
        billing_provider: BillingProvider,
        rendering_provider: RenderingProvider,
        referring_provider: typing.Optional[ReferringProvider] = OMIT,
        service_facility: typing.Optional[EncounterServiceFacilityBase] = OMIT,
        subscriber_primary: typing.Optional[SubscriberCreate] = OMIT,
        subscriber_secondary: typing.Optional[SubscriberCreate] = OMIT,
        diagnoses: typing.List[DiagnosisCreate],
        clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]] = OMIT,
        billing_notes: typing.Optional[typing.List[BillingNoteBase]] = OMIT,
        place_of_service_code: FacilityTypeCode,
        patient_histories: typing.Optional[typing.List[PatientHistoryCategory]] = OMIT,
        service_lines: typing.Optional[typing.List[ServiceLineCreate]] = OMIT,
        guarantor: typing.Optional[GuarantorCreate] = OMIT,
        external_claim_submission: typing.Optional[ExternalClaimSubmissionCreate] = OMIT,
        external_id: EncounterExternalId,
        date_of_service: Date,
        end_date_of_service: typing.Optional[Date] = OMIT,
        prior_authorization_number: typing.Optional[PriorAuthorizationNumber] = OMIT,
        patient_authorized_release: bool,
        benefits_assigned_to_provider: bool,
        provider_accepts_assignment: bool,
        appointment_type: typing.Optional[str] = OMIT,
        existing_medications: typing.Optional[typing.List[Medication]] = OMIT,
        vitals: typing.Optional[Vitals] = OMIT,
        interventions: typing.Optional[typing.List[Intervention]] = OMIT,
        pay_to_address: typing.Optional[StreetAddressLongZip] = OMIT,
        synchronicity: typing.Optional[SynchronicityType] = OMIT,
        billable_status: BillableStatusType,
        responsible_party: ResponsiblePartyType,
        additional_information: typing.Optional[str] = OMIT,
        service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode] = OMIT,
        admission_date: typing.Optional[Date] = OMIT,
        discharge_date: typing.Optional[Date] = OMIT,
        onset_of_current_illness_or_symptom_date: typing.Optional[Date] = OMIT,
        last_menstrual_period_date: typing.Optional[Date] = OMIT,
        delay_reason_code: typing.Optional[DelayReasonCode] = OMIT,
    ) -> Encounter:
        """
        Parameters:
            - patient: PatientCreate. Contains the identification information of the individual receiving medical services.

            - billing_provider: BillingProvider. The billing provider is the provider or business entity submitting the claim. Billing provider may be, but is not necessarily, the same person/NPI as the rendering provider. From a payer's perspective, this represents the person or entity being reimbursed. When a contract exists with the target payer, the billing provider should be the entity contracted with the payer. In some circumstances, this will be an individual provider. In that case, submit that provider's NPI and the tax ID (TIN) that the provider gave to the payer during contracting. In other cases, the billing entity will be a medical group. If so, submit the group NPI and the group's tax ID. Box 33 on the CMS-1500 claim form.

            - rendering_provider: RenderingProvider. The rendering provider is the practitioner -- physician, nurse practitioner, etc. -- performing the service.
                                                     For telehealth services, the rendering provider performs the visit, asynchronous communication, or other service. The rendering provider address should generally be the same as the service facility address.

            - referring_provider: typing.Optional[ReferringProvider]. The provider who referred the services that were rendered.
                                                                      All physicians who order services or refer Medicare beneficiaries must
                                                                      report this data.
                                                                      If a claim involves multiple referring physicians, create a separate
                                                                      encounter for each physician.

            - service_facility: typing.Optional[EncounterServiceFacilityBase]. Encounter Service facility is typically the location a medical service was rendered, such as a provider office or hospital. For telehealth, service facility can represent the provider's location when the service was delivered (e.g., home), or the location where an in-person visit would have taken place, whichever is easier to identify. If the provider is in-network, service facility may be defined in payer contracts. Box 32 on the CMS-1500 claim form. Note that for an in-network claim to be successfully adjudicated, the service facility address listed on claims must match what was provided to the payer during the credentialing process.

            - subscriber_primary: typing.Optional[SubscriberCreate]. Subscriber_primary is required when responsible_party is INSURANCE_PAY (i.e. when the claim should be billed to insurance).
                                                                     These are not required fields when responsible_party is SELF_PAY (i.e. when the claim should be billed to the patient).
                                                                     However, if you collect this for patients, even self-pay, we recommend including it when sending encounters to Candid.
                                                                     Note: Cash Pay is no longer a valid payer_id in v4, please use responsible party to define self-pay claims.

            - subscriber_secondary: typing.Optional[SubscriberCreate]. Please always include this when you have it, even for self-pay claims.

            - diagnoses: typing.List[DiagnosisCreate]. Ideally, this field should contain no more than 12 diagnoses. However, more diagnoses
                                                       may be submitted at this time, and coders will later prioritize the 12 that will be
                                                       submitted to the payor.

            - clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]]. Holds a collection of clinical observations made by healthcare providers during patient encounters.

            - billing_notes: typing.Optional[typing.List[BillingNoteBase]]. Spot to store misc, human-readable, notes about this encounter to be used
                                                                            in the billing process.

            - place_of_service_code: FacilityTypeCode. Box 24B on the CMS-1500 claim form. Line-level place of service is not currently supported. 02 for telemedicine, 11 for in-person. Full list [here](https://www.cms.gov/Medicare/Coding/place-of-service-codes/Place_of_Service_Code_Set).

            - patient_histories: typing.Optional[typing.List[PatientHistoryCategory]].

            - service_lines: typing.Optional[typing.List[ServiceLineCreate]]. Each service line must be linked to a diagnosis. Concretely,
                                                                              `service_line.diagnosis_pointers`must contain at least one entry which should be
                                                                              in bounds of the diagnoses list field.

            - guarantor: typing.Optional[GuarantorCreate]. Personal and contact info for the guarantor of the patient responsibility.

            - external_claim_submission: typing.Optional[ExternalClaimSubmissionCreate]. ***This field is in beta.***
                                                                                         To be included for claims that have been submitted outside of Candid.
                                                                                         Candid supports posting remits and payments to these claims and working them in-platform (e.g. editing, resubmitting).

            - external_id: EncounterExternalId. A client-specified unique ID to associate with this encounter;
                                                for example, your internal encounter ID or a Dr. Chrono encounter ID.
                                                This field should not contain PHI.
            - date_of_service: Date. Date formatted as YYYY-MM-DD; eg: 2019-08-24.
                                     This date must be the local date in the timezone where the service occurred.
                                     Box 24a on the CMS-1500 claim form.
                                     If service occurred over a range of dates, this should be the start date.
            - end_date_of_service: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.
                                                          This date must be the local date in the timezone where the service occurred.
                                                          If omitted, the Encounter is assumed to be for a single day.
                                                          Must not be temporally before the date_of_service field.
            - prior_authorization_number: typing.Optional[PriorAuthorizationNumber]. Box 23 on the CMS-1500 claim form.

            - patient_authorized_release: bool. Whether this patient has authorized the release of medical information
                                                for billing purpose.
                                                Box 12 on the CMS-1500 claim form.
            - benefits_assigned_to_provider: bool. Whether this patient has authorized insurance payments to be made to you,
                                                   not them. If false, patient may receive reimbursement.
                                                   Box 13 on the CMS-1500 claim form.
            - provider_accepts_assignment: bool. Whether you have accepted the patient's authorization for insurance payments
                                                 to be made to you, not them.
                                                 Box 27 on the CMS-1500 claim form.
            - appointment_type: typing.Optional[str]. Human-readable description of the appointment type (ex: "Acupuncture - Headaches").

            - existing_medications: typing.Optional[typing.List[Medication]].

            - vitals: typing.Optional[Vitals].

            - interventions: typing.Optional[typing.List[Intervention]].

            - pay_to_address: typing.Optional[StreetAddressLongZip]. Specifies the address to which payments for the claim should be sent.

            - synchronicity: typing.Optional[SynchronicityType]. Whether or not this was a synchronous or asynchronous encounter.
                                                                 Asynchronous encounters occur when providers and patients communicate online using
                                                                 forms, instant messaging, or other pre-recorded digital mediums.
                                                                 Synchronous encounters occur in live, real-time settings where the patient interacts
                                                                 directly with the provider, such as over video or a phone call.
            - billable_status: BillableStatusType. Defines if the Encounter is to be billed by Candid to the responsible_party.
                                                   Examples for when this should be set to NOT_BILLABLE include
                                                   if the Encounter has not occurred yet or if there is no intention of ever billing the responsible_party.
            - responsible_party: ResponsiblePartyType. Defines the party to be billed with the initial balance owed on the claim.

            - additional_information: typing.Optional[str]. Defines additional information on the claim needed by the payer.
                                                            Box 19 on the CMS-1500 claim form.
            - service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode]. 837p Loop2300 REF\*4N
                                                                                                        Required when mandated by government law or regulation to obtain authorization for specific service(s) but, for the
                                                                                                        reasons listed in one of the enum values of ServiceAuthorizationExceptionCode, the service was performed without
                                                                                                        obtaining the authorization.
            - admission_date: typing.Optional[Date]. 837p Loop2300 DTP\*435, CMS-1500 Box 18
                                                     Required on all ambulance claims when the patient was known to be admitted to the hospital.
                                                     OR
                                                     Required on all claims involving inpatient medical visits.
            - discharge_date: typing.Optional[Date]. 837p Loop2300 DTP\*096, CMS-1500 Box 18
                                                     Required for inpatient claims when the patient was discharged from the facility and the discharge date is known.
            - onset_of_current_illness_or_symptom_date: typing.Optional[Date]. 837p Loop2300 DTP\*431, CMS-1500 Box 14
                                                                               Required for the initial medical service or visit performed in response to a medical emergency when the date is available and is different than the date of service.
                                                                               OR
                                                                               This date is the onset of acute symptoms for the current illness or condition.
            - last_menstrual_period_date: typing.Optional[Date]. 837p Loop2300 DTP\*484, CMS-1500 Box 14
                                                                 Required when, in the judgment of the provider, the services on this claim are related to the patient's pregnancy.
            - delay_reason_code: typing.Optional[DelayReasonCode]. 837i Loop2300, CLM-1300 Box 20
                                                                   Code indicating the reason why a request was delayed
        """
        _request: typing.Dict[str, typing.Any] = {
            "patient": patient,
            "billing_provider": billing_provider,
            "rendering_provider": rendering_provider,
            "diagnoses": diagnoses,
            "place_of_service_code": place_of_service_code,
            "external_id": external_id,
            "date_of_service": date_of_service,
            "patient_authorized_release": patient_authorized_release,
            "benefits_assigned_to_provider": benefits_assigned_to_provider,
            "provider_accepts_assignment": provider_accepts_assignment,
            "billable_status": billable_status,
            "responsible_party": responsible_party,
        }
        if referring_provider is not OMIT:
            _request["referring_provider"] = referring_provider
        if service_facility is not OMIT:
            _request["service_facility"] = service_facility
        if subscriber_primary is not OMIT:
            _request["subscriber_primary"] = subscriber_primary
        if subscriber_secondary is not OMIT:
            _request["subscriber_secondary"] = subscriber_secondary
        if clinical_notes is not OMIT:
            _request["clinical_notes"] = clinical_notes
        if billing_notes is not OMIT:
            _request["billing_notes"] = billing_notes
        if patient_histories is not OMIT:
            _request["patient_histories"] = patient_histories
        if service_lines is not OMIT:
            _request["service_lines"] = service_lines
        if guarantor is not OMIT:
            _request["guarantor"] = guarantor
        if external_claim_submission is not OMIT:
            _request["external_claim_submission"] = external_claim_submission
        if end_date_of_service is not OMIT:
            _request["end_date_of_service"] = end_date_of_service
        if prior_authorization_number is not OMIT:
            _request["prior_authorization_number"] = prior_authorization_number
        if appointment_type is not OMIT:
            _request["appointment_type"] = appointment_type
        if existing_medications is not OMIT:
            _request["existing_medications"] = existing_medications
        if vitals is not OMIT:
            _request["vitals"] = vitals
        if interventions is not OMIT:
            _request["interventions"] = interventions
        if pay_to_address is not OMIT:
            _request["pay_to_address"] = pay_to_address
        if synchronicity is not OMIT:
            _request["synchronicity"] = synchronicity
        if additional_information is not OMIT:
            _request["additional_information"] = additional_information
        if service_authorization_exception_code is not OMIT:
            _request["service_authorization_exception_code"] = service_authorization_exception_code
        if admission_date is not OMIT:
            _request["admission_date"] = admission_date
        if discharge_date is not OMIT:
            _request["discharge_date"] = discharge_date
        if onset_of_current_illness_or_symptom_date is not OMIT:
            _request["onset_of_current_illness_or_symptom_date"] = onset_of_current_illness_or_symptom_date
        if last_menstrual_period_date is not OMIT:
            _request["last_menstrual_period_date"] = last_menstrual_period_date
        if delay_reason_code is not OMIT:
            _request["delay_reason_code"] = delay_reason_code
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "api/encounters/v4"),
            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(Encounter, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EncounterExternalIdUniquenessError":
                raise EncounterExternalIdUniquenessError(
                    pydantic.parse_obj_as(EncounterExternalIdUniquenessErrorType, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "EncounterPatientControlNumberUniquenessError":
                raise EncounterPatientControlNumberUniquenessError(
                    pydantic.parse_obj_as(EncounterPatientControlNumberUniquenessErrorType, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "EntityNotFoundError":
                raise EntityNotFoundError(
                    pydantic.parse_obj_as(EntityNotFoundErrorMessage, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "EncounterGuarantorMissingContactInfoError":
                raise EncounterGuarantorMissingContactInfoError(
                    pydantic.parse_obj_as(EncounterGuarantorMissingContactInfoErrorType, _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "HttpRequestValidationsError":
                raise HttpRequestValidationsError(
                    pydantic.parse_obj_as(typing.List[RequestValidationError], _response_json["content"])  # type: ignore
                )
            if _response_json["errorName"] == "CashPayPayerError":
                raise CashPayPayerError(
                    pydantic.parse_obj_as(CashPayPayerErrorMessage, _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update(
        self,
        encounter_id: EncounterId,
        *,
        prior_authorization_number: typing.Optional[PriorAuthorizationNumber] = OMIT,
        external_id: typing.Optional[EncounterExternalId] = OMIT,
        date_of_service: typing.Optional[Date] = OMIT,
        diagnosis_ids: typing.Optional[typing.List[DiagnosisId]] = OMIT,
        tag_ids: typing.Optional[typing.List[TagId]] = OMIT,
        clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]] = OMIT,
        pay_to_address: typing.Optional[StreetAddressLongZip] = OMIT,
        billable_status: typing.Optional[BillableStatusType] = OMIT,
        responsible_party: typing.Optional[ResponsiblePartyType] = OMIT,
        provider_accepts_assignment: typing.Optional[bool] = OMIT,
        benefits_assigned_to_provider: typing.Optional[bool] = OMIT,
        synchronicity: typing.Optional[SynchronicityType] = OMIT,
        place_of_service_code: typing.Optional[FacilityTypeCode] = OMIT,
        appointment_type: typing.Optional[str] = OMIT,
        end_date_of_service: typing.Optional[Date] = OMIT,
        subscriber_primary: typing.Optional[SubscriberCreate] = OMIT,
        subscriber_secondary: typing.Optional[SubscriberCreate] = OMIT,
        additional_information: typing.Optional[str] = OMIT,
        service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode] = OMIT,
        admission_date: typing.Optional[Date] = OMIT,
        discharge_date: typing.Optional[Date] = OMIT,
        onset_of_current_illness_or_symptom_date: typing.Optional[Date] = OMIT,
        last_menstrual_period_date: typing.Optional[Date] = OMIT,
        delay_reason_code: typing.Optional[DelayReasonCode] = OMIT,
    ) -> Encounter:
        """
        Parameters:
            - encounter_id: EncounterId.

            - prior_authorization_number: typing.Optional[PriorAuthorizationNumber]. Box 23 on the CMS-1500 claim form.

            - external_id: typing.Optional[EncounterExternalId]. A client-specified unique ID to associate with this encounter;
                                                                 for example, your internal encounter ID or a Dr. Chrono encounter ID.
                                                                 This field should not contain PHI.

            - date_of_service: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-24.
                                                      This date must be the local date in the timezone where the service occurred.
                                                      Box 24a on the CMS-1500 claim form.
                                                      If service occurred over a range of dates, this should be the start date.

            - diagnosis_ids: typing.Optional[typing.List[DiagnosisId]]. Ideally, this field should contain no more than 12 diagnoses. However, more diagnoses
                                                                        may be submitted at this time, and coders will later prioritize the 12 that will be
                                                                        submitted to the payor.

            - tag_ids: typing.Optional[typing.List[TagId]]. Names of tags that should be on the encounter.

            - clinical_notes: typing.Optional[typing.List[ClinicalNoteCategoryCreate]]. Holds a collection of clinical observations made by healthcare providers during patient encounters.

            - pay_to_address: typing.Optional[StreetAddressLongZip]. Specifies the address to which payments for the claim should be sent.

            - billable_status: typing.Optional[BillableStatusType]. Defines if the Encounter is to be billed by Candid to the responsible_party. Examples for when this should be set to NOT_BILLABLE include if the Encounter has not occurred yet or if there is no intention of ever billing the responsible_party.

            - responsible_party: typing.Optional[ResponsiblePartyType]. Defines the party to be billed with the initial balance owed on the claim. Use SELF_PAY if you intend to bill self pay/cash pay.

            - provider_accepts_assignment: typing.Optional[bool]. Whether you have accepted the patient's authorization for insurance payments to be made to you, not them. Box 27 on the CMS-1500 claim form.

            - benefits_assigned_to_provider: typing.Optional[bool]. Whether this patient has authorized insurance payments to be made to you, not them. If false, patient may receive reimbursement. Box 13 on the CMS-1500 claim form.

            - synchronicity: typing.Optional[SynchronicityType]. Whether or not this was a synchronous or asynchronous encounter. Asynchronous encounters occur when providers and patients communicate online using forms, instant messaging, or other pre-recorded digital mediums. Synchronous encounters occur in live, real-time settings where the patient interacts directly with the provider, such as over video or a phone call.

            - place_of_service_code: typing.Optional[FacilityTypeCode]. Box 24B on the CMS-1500 claim form. Line-level place of service is not currently supported. 02 for telemedicine, 11 for in-person. Full list [here](https://www.cms.gov/Medicare/Coding/place-of-service-codes/Place_of_Service_Code_Set).

            - appointment_type: typing.Optional[str]. Human-readable description of the appointment type (ex: "Acupuncture - Headaches").

            - end_date_of_service: typing.Optional[Date]. Date formatted as YYYY-MM-DD; eg: 2019-08-25.
                                                          This date must be the local date in the timezone where the service occurred.
                                                          If omitted, the Encounter is assumed to be for a single day.
                                                          Must not be temporally before the date_of_service field.

            - subscriber_primary: typing.Optional[SubscriberCreate]. Contains details of the primary insurance subscriber.

            - subscriber_secondary: typing.Optional[SubscriberCreate]. Contains details of the secondary insurance subscriber.

            - additional_information: typing.Optional[str]. Defines additional information on the claim needed by the payer.
                                                            Box 19 on the CMS-1500 claim form.

            - service_authorization_exception_code: typing.Optional[ServiceAuthorizationExceptionCode]. 837p Loop2300 REF*4N
                                                                                                        Required when mandated by government law or regulation to obtain authorization for specific service(s) but, for the
                                                                                                        reasons listed in one of the enum values of ServiceAuthorizationExceptionCode, the service was performed without
                                                                                                        obtaining the authorization.

            - admission_date: typing.Optional[Date]. 837p Loop2300 DTP*435, CMS-1500 Box 18
                                                     Required on all ambulance claims when the patient was known to be admitted to the hospital.
                                                     OR
                                                     Required on all claims involving inpatient medical visits.

            - discharge_date: typing.Optional[Date]. 837p Loop2300 DTP*096, CMS-1500 Box 18
                                                     Required for inpatient claims when the patient was discharged from the facility and the discharge date is known.

            - onset_of_current_illness_or_symptom_date: typing.Optional[Date]. 837p Loop2300 DTP*431, CMS-1500 Box 14
                                                                               Required for the initial medical service or visit performed in response to a medical emergency when the date is available and is different than the date of service.
                                                                               OR
                                                                               This date is the onset of acute symptoms for the current illness or condition.

            - last_menstrual_period_date: typing.Optional[Date]. 837p Loop2300 DTP*484, CMS-1500 Box 14
                                                                 Required when, in the judgment of the provider, the services on this claim are related to the patient's pregnancy.

            - delay_reason_code: typing.Optional[DelayReasonCode]. 837i Loop2300, CLM-1300 Box 20
                                                                   Code indicating the reason why a request was delayed

        """
        _request: typing.Dict[str, typing.Any] = {}
        if prior_authorization_number is not OMIT:
            _request["prior_authorization_number"] = prior_authorization_number
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if date_of_service is not OMIT:
            _request["date_of_service"] = date_of_service
        if diagnosis_ids is not OMIT:
            _request["diagnosis_ids"] = diagnosis_ids
        if tag_ids is not OMIT:
            _request["tag_ids"] = tag_ids
        if clinical_notes is not OMIT:
            _request["clinical_notes"] = clinical_notes
        if pay_to_address is not OMIT:
            _request["pay_to_address"] = pay_to_address
        if billable_status is not OMIT:
            _request["billable_status"] = billable_status
        if responsible_party is not OMIT:
            _request["responsible_party"] = responsible_party
        if provider_accepts_assignment is not OMIT:
            _request["provider_accepts_assignment"] = provider_accepts_assignment
        if benefits_assigned_to_provider is not OMIT:
            _request["benefits_assigned_to_provider"] = benefits_assigned_to_provider
        if synchronicity is not OMIT:
            _request["synchronicity"] = synchronicity
        if place_of_service_code is not OMIT:
            _request["place_of_service_code"] = place_of_service_code
        if appointment_type is not OMIT:
            _request["appointment_type"] = appointment_type
        if end_date_of_service is not OMIT:
            _request["end_date_of_service"] = end_date_of_service
        if subscriber_primary is not OMIT:
            _request["subscriber_primary"] = subscriber_primary
        if subscriber_secondary is not OMIT:
            _request["subscriber_secondary"] = subscriber_secondary
        if additional_information is not OMIT:
            _request["additional_information"] = additional_information
        if service_authorization_exception_code is not OMIT:
            _request["service_authorization_exception_code"] = service_authorization_exception_code
        if admission_date is not OMIT:
            _request["admission_date"] = admission_date
        if discharge_date is not OMIT:
            _request["discharge_date"] = discharge_date
        if onset_of_current_illness_or_symptom_date is not OMIT:
            _request["onset_of_current_illness_or_symptom_date"] = onset_of_current_illness_or_symptom_date
        if last_menstrual_period_date is not OMIT:
            _request["last_menstrual_period_date"] = last_menstrual_period_date
        if delay_reason_code is not OMIT:
            _request["delay_reason_code"] = delay_reason_code
        _response = await self._client_wrapper.httpx_client.request(
            "PATCH",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"api/encounters/v4/{encounter_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(Encounter, _response_json)  # type: ignore
        if "errorName" in _response_json:
            if _response_json["errorName"] == "EncounterExternalIdUniquenessError":
                raise EncounterExternalIdUniquenessError(
                    pydantic.parse_obj_as(EncounterExternalIdUniquenessErrorType, _response_json["content"])  # type: ignore
                )
            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"] == "HttpRequestValidationsError":
                raise HttpRequestValidationsError(
                    pydantic.parse_obj_as(typing.List[RequestValidationError], _response_json["content"])  # type: ignore
                )
        raise ApiError(status_code=_response.status_code, body=_response_json)
