"""Appointment DTOs — Phase 13.1."""
from __future__ import annotations

from datetime import datetime, time
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field

from app.models.types import AppointmentStatus, DayOfWeek, LifecycleStatus
from app.schemas.common import ORMBase

_FORBID = ConfigDict(extra="forbid")


class ScheduleCreate(BaseModel):
    model_config = _FORBID
    clinic_id: UUID
    doctor_id: UUID
    department_id: UUID | None = None
    code: str = Field(max_length=50)
    name: str = Field(max_length=255)
    day_of_week: DayOfWeek
    start_time: time
    end_time: time
    slot_duration_minutes: int = Field(default=30, ge=5, le=480)
    is_active: bool = True
    metadata_json: dict | None = None


class ScheduleRead(ORMBase):
    id: UUID
    tenant_id: UUID
    clinic_id: UUID
    doctor_id: UUID
    department_id: UUID | None
    code: str
    name: str
    day_of_week: DayOfWeek
    start_time: time
    end_time: time
    slot_duration_minutes: int
    is_active: bool
    metadata_json: dict | None
    is_deleted: bool
    created_at: datetime
    updated_at: datetime


class AvailabilityWindowCreate(BaseModel):
    model_config = _FORBID
    clinic_id: UUID
    doctor_id: UUID
    code: str = Field(max_length=50)
    starts_at: datetime
    ends_at: datetime
    is_bookable: bool = True
    metadata_json: dict | None = None


class AvailabilityWindowRead(ORMBase):
    id: UUID
    tenant_id: UUID
    clinic_id: UUID
    doctor_id: UUID
    code: str
    starts_at: datetime
    ends_at: datetime
    is_bookable: bool
    metadata_json: dict | None
    is_deleted: bool
    created_at: datetime
    updated_at: datetime


class AppointmentTypeCreate(BaseModel):
    model_config = _FORBID
    clinic_id: UUID
    code: str = Field(max_length=50)
    name: str = Field(max_length=255)
    description: str | None = None
    default_duration_minutes: int = Field(default=30, ge=5, le=480)
    status: LifecycleStatus = LifecycleStatus.ACTIVE


class AppointmentTypeRead(ORMBase):
    id: UUID
    tenant_id: UUID
    clinic_id: UUID
    code: str
    name: str
    description: str | None
    default_duration_minutes: int
    status: LifecycleStatus
    is_deleted: bool
    created_at: datetime
    updated_at: datetime


class AppointmentCreate(BaseModel):
    model_config = _FORBID
    clinic_id: UUID
    doctor_id: UUID
    patient_id: UUID
    department_id: UUID | None = None
    appointment_type_id: UUID | None = None
    code: str = Field(max_length=50)
    scheduled_start: datetime
    scheduled_end: datetime
    notes: str | None = None
    metadata_json: dict | None = None


class AppointmentReschedule(BaseModel):
    model_config = _FORBID
    scheduled_start: datetime
    scheduled_end: datetime
    version: int = Field(ge=1)
    reason: str | None = Field(default=None, max_length=500)


class AppointmentLifecycleRequest(BaseModel):
    model_config = _FORBID
    version: int = Field(ge=1)
    reason: str | None = Field(default=None, max_length=500)


class AppointmentRead(ORMBase):
    id: UUID
    tenant_id: UUID
    clinic_id: UUID
    doctor_id: UUID
    patient_id: UUID
    department_id: UUID | None
    appointment_type_id: UUID | None
    code: str
    status: AppointmentStatus
    scheduled_start: datetime
    scheduled_end: datetime
    notes: str | None
    status_reason: str | None
    status_changed_at: datetime | None
    reminder_scheduled: bool
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_at: datetime
    updated_at: datetime


class AppointmentListResponse(BaseModel):
    items: list[AppointmentRead]
    total: int
    page: int
    page_size: int


class WaitingListEntryCreate(BaseModel):
    model_config = _FORBID
    clinic_id: UUID
    doctor_id: UUID | None = None
    patient_id: UUID
    appointment_type_id: UUID | None = None
    code: str = Field(max_length=50)
    preferred_date: str | None = Field(default=None, max_length=32)
    notes: str | None = None
    priority: int = Field(default=100, ge=1, le=1000)


class WaitingListEntryRead(ORMBase):
    id: UUID
    tenant_id: UUID
    clinic_id: UUID
    doctor_id: UUID | None
    patient_id: UUID
    appointment_type_id: UUID | None
    code: str
    preferred_date: str | None
    notes: str | None
    priority: int
    is_deleted: bool
    created_at: datetime
    updated_at: datetime
