"""
Schemas for Appointments and Appointment Slots.
"""

from datetime import date, datetime
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field

from app.models.appointment import AppointmentStatus, BookingChannel

# ── Appointment Slot Schemas ──────────────────────────────────────────────────


class AppointmentSlotBase(BaseModel):
    """Base fields for an appointment slot."""

    start_at: datetime = Field(..., description="Start of the booking window")
    end_at: datetime = Field(..., description="End of the booking window")
    capacity: int = Field(1, ge=1, description="Maximum number of bookings allowed")
    is_active: bool = Field(True, description="Whether slot is open for bookings")


class AppointmentSlotCreate(AppointmentSlotBase):
    """Payload to create an appointment slot."""

    lab_id: UUID | None = Field(default=None, description="Branch lab ID (defaults to primary if omitted)")


class AppointmentSlotUpdate(BaseModel):
    """Payload to update an appointment slot."""

    start_at: datetime | None = None
    end_at: datetime | None = None
    capacity: int | None = Field(None, ge=1)
    is_active: bool | None = None


class AppointmentSlotResponse(BaseModel):
    """Response schema for an appointment slot."""

    id: UUID
    lab_id: UUID
    start_at: datetime
    end_at: datetime
    capacity: int
    booked_count: int
    is_active: bool
    is_full: bool
    available_slots: int
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# ── Appointment Schemas ───────────────────────────────────────────────────────


class AppointmentCreate(BaseModel):
    """Payload to book an appointment."""

    lab_id: UUID | None = Field(default=None, description="Branch lab ID (defaults to primary if omitted)")
    patient_id: UUID = Field(..., description="Patient ID")
    slot_id: UUID | None = Field(None, description="Booking window slot ID (null for walk-in)")
    booked_via: BookingChannel = Field(
        BookingChannel.WALK_IN, description="Booking channel (walk_in, phone, online, portal)"
    )
    contact_name: str | None = Field(None, max_length=200, description="Contact name if booking on behalf")
    contact_phone: str | None = Field(None, max_length=20, description="Contact phone if booking on behalf")
    notes: str | None = Field(None, description="Optional booking notes")


class QuickAppointmentCreate(BaseModel):
    """Payload for quick appointment booking (online guest or staff reception desk)."""

    patient_id: UUID | None = Field(default=None, description="Existing patient ID if already registered")
    name: str | None = Field(default=None, max_length=200, description="Patient full name if unregistered")
    phone: str | None = Field(default=None, max_length=20, description="Patient contact mobile phone")
    email: str | None = Field(
        default=None, max_length=255, description="Patient email address for booking confirmation"
    )
    gender: str | None = Field(default="male", description="male, female, or other")
    age: int | None = Field(default=None, ge=0, le=150, description="Age in years")
    address: str | None = Field(default=None, description="Patient address")

    slot_id: UUID | None = Field(default=None, description="Selected booking window slot ID")
    target_date: date | None = Field(
        default=None, description="Date (YYYY-MM-DD) if auto-selecting/ensuring slot"
    )
    time_window: str | None = Field(default=None, description="Time window text (e.g. 07:30 - 08:30)")
    booked_via: BookingChannel = Field(
        default=BookingChannel.ONLINE, description="Channel (online, phone, walk_in)"
    )
    collection_type: str | None = Field(default="lab", description="lab or home")
    notes: str | None = Field(default=None, description="Optional booking notes / test inquiry reason")
    lab_id: UUID | None = Field(default=None, description="Lab branch ID")


class AppointmentUpdate(BaseModel):
    """Payload to update an appointment."""

    slot_id: UUID | None = None
    contact_name: str | None = Field(None, max_length=200)
    contact_phone: str | None = Field(None, max_length=20)
    notes: str | None = None


class AppointmentRescheduleRequest(BaseModel):
    """Move booking to another slot window."""

    slot_id: UUID = Field(..., description="Target slot ID")


class AppointmentResponse(BaseModel):
    """Response schema for an appointment."""

    id: UUID
    lab_id: UUID
    patient_id: UUID
    slot_id: UUID | None = None
    visit_order_id: UUID | None = None
    status: AppointmentStatus
    booked_via: BookingChannel
    contact_name: str | None = None
    contact_phone: str | None = None
    notes: str | None = None
    patient_name: str | None = None
    patient_phone: str | None = None
    scheduled_at: datetime | None = Field(
        None,
        description="Slot start time when booked, otherwise created_at for walk-ins",
    )
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)
