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

import datetime as dt
import typing

import pydantic
from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
from .....commons.types.claim_id import ClaimId
from .....commons.types.date_range_optional_end import DateRangeOptionalEnd
from .....commons.types.decimal import Decimal
from .....commons.types.facility_type_code import FacilityTypeCode
from .....commons.types.procedure_modifier import ProcedureModifier
from .....commons.types.service_line_id import ServiceLineId
from .....commons.types.service_line_units import ServiceLineUnits
from .....diagnoses.types.diagnosis_id import DiagnosisId
from .....encounter_providers.resources.v_2.types.encounter_provider import EncounterProvider
from .....invoices.resources.v_2.types.invoice_info import InvoiceInfo
from .....invoices.types.invoice import Invoice
from .drug_identification import DrugIdentification
from .service_line_adjustment import ServiceLineAdjustment
from .service_line_denial_reason import ServiceLineDenialReason
from .service_line_era_data import ServiceLineEraData
from .test_result import TestResult


class ServiceLine(UniversalBaseModel):
    """
    Examples
    --------
    import datetime
    import uuid

    from candid.resources.commons import (
        DateRangeOptionalEnd,
        FacilityTypeCode,
        ProcedureModifier,
        ServiceLineUnits,
    )
    from candid.resources.invoices import Invoice, InvoiceItem, InvoiceStatus
    from candid.resources.service_lines.resources.v_2 import (
        DenialReasonContent,
        ServiceLine,
        ServiceLineAdjustment,
        ServiceLineDenialReason,
        ServiceLineEraData,
        TestResult,
        TestResultType,
    )

    ServiceLine(
        created_at=datetime.datetime.fromisoformat(
            "2023-01-01 00:00:00+00:00",
        ),
        modifiers=[ProcedureModifier.TWENTY_TWO],
        charge_amount_cents=10000,
        allowed_amount_cents=8000,
        insurance_balance_cents=0,
        patient_balance_cents=2000,
        paid_amount_cents=8000,
        patient_responsibility_cents=2000,
        diagnosis_id_zero=uuid.UUID(
            "4ac84bcd-12f5-4f86-a57b-e06749127c98",
        ),
        diagnosis_id_one=uuid.UUID(
            "eea5ca5a-8b43-45fd-8cbd-c6cc1103e759",
        ),
        diagnosis_id_two=uuid.UUID(
            "5c4aa029-2db9-4202-916e-e93c708f65ff",
        ),
        diagnosis_id_three=uuid.UUID(
            "81795126-a3ac-443c-b47e-7259a16ab4a2",
        ),
        service_line_era_data=ServiceLineEraData(
            service_line_adjustments=[
                ServiceLineAdjustment(
                    created_at=datetime.datetime.fromisoformat(
                        "2023-01-01 00:00:00+00:00",
                    ),
                    adjustment_group_code="CO",
                    adjustment_reason_code="CO",
                    adjustment_amount_cents=1000,
                    adjustment_note="test_note",
                )
            ],
            remittance_advice_remark_codes=["N362"],
        ),
        service_line_manual_adjustments=[
            ServiceLineAdjustment(
                created_at=datetime.datetime.fromisoformat(
                    "2023-01-01 00:00:00+00:00",
                ),
                adjustment_group_code="CO",
                adjustment_reason_code="CO",
                adjustment_amount_cents=1000,
                adjustment_note="test_note",
            )
        ],
        related_invoices=[
            Invoice(
                id=uuid.UUID(
                    "901be2f1-41bc-456e-9987-4fe2f84f9d75",
                ),
                created_at=datetime.datetime.fromisoformat(
                    "2023-01-01 00:00:00+00:00",
                ),
                updated_at=datetime.datetime.fromisoformat(
                    "2023-01-01 00:00:00+00:00",
                ),
                organzation_id=uuid.UUID(
                    "f13f73d4-4344-46ea-9d93-33bcffbb9f36",
                ),
                source_id="9B626577-8808-4F28-9ED1-F0DFF0D49BBC",
                source_customer_id="624D1972-8C69-4C2F-AEFA-10856F734DB3",
                patient_external_id="10FED4D6-4C5A-48DF-838A-EEF45A74788D",
                note="test_note",
                due_date="2023-10-10",
                status=InvoiceStatus.DRAFT,
                url="https://example.com",
                customer_invoice_url="https://example.com",
                items=[
                    InvoiceItem(
                        service_line_id=uuid.UUID(
                            "ced00f23-6e68-4678-9dbc-f5aa2969a565",
                        ),
                        amount_cents=500,
                    )
                ],
            )
        ],
        denial_reason=ServiceLineDenialReason(
            reason=DenialReasonContent.AUTHORIZATION_REQUIRED,
        ),
        place_of_service_code=FacilityTypeCode.PHARMACY,
        service_line_id=uuid.UUID(
            "ced00f23-6e68-4678-9dbc-f5aa2969a565",
        ),
        procedure_code="99213",
        quantity="1",
        units=ServiceLineUnits.MJ,
        claim_id=uuid.UUID(
            "026a1fb8-748e-4859-a2d7-3ea9e07d25ae",
        ),
        date_of_service_range=DateRangeOptionalEnd(
            start_date="2023-01-01",
            end_date="2023-01-03",
        ),
        date_of_service=datetime.date.fromisoformat(
            "2023-01-01",
        ),
        end_date_of_service=datetime.date.fromisoformat(
            "2023-01-03",
        ),
        test_results=[
            TestResult(
                result_type=TestResultType.HEMOGLOBIN,
                value=51.0,
            ),
            TestResult(
                result_type=TestResultType.LDL,
                value=110.0,
            ),
        ],
    )
    """

    created_at: dt.datetime
    modifiers: typing.Optional[typing.List[ProcedureModifier]] = None
    charge_amount_cents: typing.Optional[int] = None
    allowed_amount_cents: typing.Optional[int] = None
    insurance_balance_cents: typing.Optional[int] = None
    patient_balance_cents: typing.Optional[int] = None
    paid_amount_cents: typing.Optional[int] = None
    primary_paid_amount_cents: typing.Optional[int] = None
    secondary_paid_amount_cents: typing.Optional[int] = None
    tertiary_paid_amount_cents: typing.Optional[int] = None
    patient_responsibility_cents: typing.Optional[int] = None
    copay_cents: typing.Optional[int] = None
    coinsurance_cents: typing.Optional[int] = None
    deductible_cents: typing.Optional[int] = None
    diagnosis_id_zero: typing.Optional[DiagnosisId] = None
    diagnosis_id_one: typing.Optional[DiagnosisId] = None
    diagnosis_id_two: typing.Optional[DiagnosisId] = None
    diagnosis_id_three: typing.Optional[DiagnosisId] = None
    drug_identification: typing.Optional[DrugIdentification] = None
    service_line_era_data: typing.Optional[ServiceLineEraData] = None
    service_line_manual_adjustments: typing.Optional[typing.List[ServiceLineAdjustment]] = None
    related_invoices: typing.Optional[typing.List[Invoice]] = None
    related_invoice_info: typing.Optional[typing.List[InvoiceInfo]] = None
    denial_reason: typing.Optional[ServiceLineDenialReason] = None
    place_of_service_code: typing.Optional[FacilityTypeCode] = pydantic.Field(default=None)
    """
    837p Loop2300, SV105. This enum is not used or required in 837i claims. If your organization does not intend to submit claims with a different place of service at the service line level, this field should not be populated. 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).
    """

    place_of_service_code_as_submitted: typing.Optional[FacilityTypeCode] = pydantic.Field(default=None)
    """
    837p Loop2300, SV105. 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).
    """

    service_line_id: ServiceLineId
    procedure_code: str
    ordering_provider: typing.Optional[EncounterProvider] = None
    revenue_code: typing.Optional[str] = pydantic.Field(default=None)
    """
    A 4 digit code that specifies facility department or type of service arrangement for institutional service line items (837i). This code is not required for professional claim billing (837p).
    """

    quantity: Decimal = pydantic.Field()
    """
    String representation of a Decimal that can be parsed by most libraries.
    For professional claims, a ServiceLine quantity cannot contain more than one digit of precision
    (Example: 1.1 is valid, 1.11 is not). For institutional claims, a ServiceLine quantity cannot contain
    more than three decimal digits of precision.
    """

    units: ServiceLineUnits
    claim_id: ClaimId
    date_of_service_range: DateRangeOptionalEnd = pydantic.Field()
    """
    A range of dates of service for this service line. If the service line is for a single date, the end date
    will be empty.
    """

    description: typing.Optional[str] = pydantic.Field(default=None)
    """
    A free-form description to clarify the related data elements and their content. Maps to SV1-01, C003-07 on a 837-P and SV2-02, C003-07 on a 837-I form.
    """

    date_of_service: dt.date
    end_date_of_service: typing.Optional[dt.date] = None
    test_results: typing.Optional[typing.List[TestResult]] = pydantic.Field(default=None)
    """
    Contains a list of test results. Test result types may map to MEA-02 on the 837-P (ex: Hemoglobin, Hematocrit).
    This is unused by 837-i and ignored for institutional service lines.
    No more than 5 MEA-02 test results may be submitted per service line.
    """

    has_epsdt_indicator: typing.Optional[bool] = pydantic.Field(default=None)
    """
    Maps to SV1-11 on the 837-P and Box 24H on the CMS-1500.
    If the value is true, the box will be populated with "Y". Otherwise, the box will not be populated.
    """

    has_family_planning_indicator: typing.Optional[bool] = pydantic.Field(default=None)
    """
    Maps to SV1-12 on the 837-P and Box 24I on the CMS-1500.
    If the value is true, the box will be populated with "Y". Otherwise, the box will not be populated.
    """

    note: typing.Optional[str] = pydantic.Field(default=None)
    """
    Maps to NTE02 loop 2400 on the EDI 837.
    """

    prior_authorization_number: typing.Optional[str] = pydantic.Field(default=None)
    """
    Prior authorization number for this service line. Maps to the appropriate REF segment on Loop 2400 of the EDI 837p. This is not used for institutional claims (EDI 837i).
    """

    external_id: typing.Optional[str] = pydantic.Field(default=None)
    """
    An external identifier for this service line. This is not used in the EDI 837, but can be used to identify the service line in external systems.
    This field should not contain PHI. Must be unique on a given claim.
    """

    if IS_PYDANTIC_V2:
        model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True)  # type: ignore # Pydantic v2
    else:

        class Config:
            frozen = True
            smart_union = True
            extra = pydantic.Extra.allow
