"""
Schemas for Visit Orders, line items, and lifecycle management.
"""

from datetime import date, datetime
from decimal import Decimal
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field

from app.models.order import OrderStatus, OrderTestStatus


class OrderTestResponse(BaseModel):
    """Schema representing an individual test on an order."""

    id: UUID
    order_id: UUID
    test_id: UUID
    price_at_order: Decimal
    status: OrderTestStatus
    test_name: str | None = None
    test_code: str | None = None

    model_config = ConfigDict(from_attributes=True)


class OrderPackageResponse(BaseModel):
    """Schema representing a package on an order."""

    id: UUID
    order_id: UUID
    package_id: UUID
    price_at_order: Decimal
    package_name: str | None = None
    package_code: str | None = None

    model_config = ConfigDict(from_attributes=True)


class TestParameterScope(BaseModel):
    """Analyte-level scope: only these parameters of the test were ordered."""

    test_id: UUID = Field(..., description="Test ID this scope applies to")
    parameter_ids: list[UUID] = Field(..., min_length=1, description="Ordered analyte IDs")


class OrderCreate(BaseModel):
    """Payload to create a new visit order."""

    lab_id: UUID | None = Field(default=None, description="Branch lab ID (defaults to primary if omitted)")
    patient_id: UUID = Field(..., description="Patient ID")
    appointment_id: UUID | None = Field(None, description="Optional appointment link")
    referral_id: UUID | None = Field(None, description="Optional registered referral ID")
    referred_by_custom: str | None = Field(None, max_length=300, description="Custom referral text")
    next_date: date | None = Field(None, description="Optional follow-up date")
    destination_country: str | None = Field(None, max_length=100, description="Country for report")
    notes: str | None = Field(None, description="Internal order remarks")
    test_ids: list[UUID] = Field(default_factory=list, description="IDs of tests to book")
    package_ids: list[UUID] = Field(default_factory=list, description="IDs of packages to book")
    test_parameters: list[TestParameterScope] = Field(
        default_factory=list,
        description="Optional analyte-level scopes (only listed analytes are enterable)",
    )


class OrderUpdate(BaseModel):
    """Payload to update order details."""

    referred_by_custom: str | None = Field(None, min_length=1, max_length=300)
    next_date: date | None = None
    destination_country: str | None = Field(None, max_length=100)
    notes: str | None = None
    status: OrderStatus | None = None


class OrderAttachTests(BaseModel):
    """Payload to attach panels to an existing order (e.g. legacy test-less orders)."""

    test_ids: list[UUID] = Field(..., min_length=1, description="Test IDs to add (duplicates skipped)")


class OrderAttachPackages(BaseModel):
    """Payload to attach health packages to an existing order."""

    package_ids: list[UUID] = Field(..., min_length=1, description="Package IDs to add (duplicates skipped)")


class VisitOrderResponse(BaseModel):
    """Summary response schema for a visit order."""

    id: UUID
    lab_id: UUID
    patient_id: UUID
    appointment_id: UUID | None = None
    referral_id: UUID | None = None
    order_number: str
    status: OrderStatus
    referred_by_custom: str | None = None
    next_date: date | None = None
    destination_country: str | None = None
    is_abroad: bool = False
    notes: str | None = None
    total_amount: Decimal = Decimal("0.00")
    patient_name: str | None = None
    patient_code: str | None = None
    bill_number: str | None = None
    bill_status: str | None = None
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class VisitOrderDetailResponse(VisitOrderResponse):
    """Detailed response schema including patient summary and item breakdowns."""

    patient_name: str | None = None
    patient_code: str | None = None
    tests: list[OrderTestResponse] = Field(default_factory=list)
    packages: list[OrderPackageResponse] = Field(default_factory=list)
