"""Scheduling request schemas (legacy /services router — INDL-10).

INDL-34 reshaped the underlying `services` table: the old boolean flags
`email_family` / `add_to_briefing` / `reminder_24h` and the `run_sheet_milestones`
JSONB column were dropped. The legacy notify flags now map onto the new
`notify_family_confirmation` / `notify_family_reminder_24h` columns so this router
keeps working for the existing admin frontend. Crew assignments now live in
`service_crew_assignments` (crew_members), not the dropped `service_staff_assignments`.
"""
from datetime import date, time
from typing import List, Optional
from uuid import UUID

from pydantic import BaseModel, field_validator

from src.core.validators import validate_phone

# Legal states on the shared `services` table (INDL-34). The legacy /services
# router may only set draft / awaiting_family_confirm. `confirmed` is reachable
# ONLY via PATCH /api/v1/scheduling/{id}/status — legacy writes that try to set
# it are rejected with 422 to preserve the status-FSM invariant.
_ALLOWED_STATUSES = {"draft", "awaiting_family_confirm", "confirmed"}
_LEGACY_WRITABLE_STATUSES = {"draft", "awaiting_family_confirm"}
_CONFIRM_VIA_PATCH_MSG = (
    "Confirming a service must be done via PATCH /api/v1/scheduling/{id}/status."
)


def _validate_legacy_status(v: Optional[str]) -> Optional[str]:
    """Reject unknown statuses and block the draft/awaiting -> confirmed jump."""
    if v is None:
        return v
    if v not in _ALLOWED_STATUSES:
        raise ValueError(
            "status must be one of: draft, awaiting_family_confirm, confirmed"
        )
    if v not in _LEGACY_WRITABLE_STATUSES:
        raise ValueError(_CONFIRM_VIA_PATCH_MSG)
    return v


class ServiceCreate(BaseModel):
    service_type: str  # 'interment' | 'memorial' | 'foundation_pour' | 'closure'
    record_id: Optional[UUID] = None
    plot_id: Optional[UUID] = None
    section_id: Optional[UUID] = None
    scheduled_date: date
    scheduled_time: time
    duration_minutes: Optional[int] = 60
    officiant: Optional[str] = None
    family_contact_name: Optional[str] = None
    family_contact_phone: Optional[str] = None
    expected_attendees: Optional[int] = None
    equipment_needed: Optional[str] = None
    notes: Optional[str] = None
    status: str = "draft"  # 'draft' | 'awaiting_family_confirm' | 'confirmed'
    # Legacy flag names map onto the new notify_* columns (INDL-34).
    notify_family_confirmation: bool = False
    notify_family_reminder_24h: bool = False
    assigned_crew_ids: List[UUID] = []

    @field_validator('family_contact_phone', mode='before')
    @classmethod
    def _validate_phone(cls, v: Optional[str]) -> Optional[str]:
        return validate_phone(v)

    @field_validator('status')
    @classmethod
    def _validate_status(cls, v: Optional[str]) -> Optional[str]:
        return _validate_legacy_status(v)


class ExportWeekPdfRequest(BaseModel):
    week_start: date


class ServiceUpdate(BaseModel):
    service_type: Optional[str] = None
    record_id: Optional[UUID] = None
    plot_id: Optional[UUID] = None
    section_id: Optional[UUID] = None
    scheduled_date: Optional[date] = None
    scheduled_time: Optional[time] = None
    duration_minutes: Optional[int] = None
    officiant: Optional[str] = None
    family_contact_name: Optional[str] = None
    family_contact_phone: Optional[str] = None
    expected_attendees: Optional[int] = None
    equipment_needed: Optional[str] = None
    notes: Optional[str] = None
    status: Optional[str] = None
    notify_family_confirmation: Optional[bool] = None
    notify_family_reminder_24h: Optional[bool] = None
    assigned_crew_ids: Optional[List[UUID]] = None

    @field_validator('family_contact_phone', mode='before')
    @classmethod
    def _validate_phone(cls, v: Optional[str]) -> Optional[str]:
        return validate_phone(v)

    @field_validator('status')
    @classmethod
    def _validate_status(cls, v: Optional[str]) -> Optional[str]:
        return _validate_legacy_status(v)
