"""Forms, surveys & appointment DTOs — Phase 11.6."""
from __future__ import annotations

from datetime import datetime
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field

from app.models.types import (
    AppointmentBookingStatus,
    AppointmentPageStatus,
    FormStatus,
    FormSubmissionStatus,
    SurveyResponseStatus,
    SurveyStatus,
)
from app.schemas.common import ORMBase

_FORBID = ConfigDict(extra="forbid")


class ExperienceFormCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID | None = None
    page_id: UUID | None = None
    code: str = Field(max_length=50)
    name: str = Field(max_length=255)
    description: str | None = None
    status: FormStatus = FormStatus.DRAFT
    form_schema_json: dict | None = None
    submit_action_json: dict | None = None
    metadata_json: dict | None = None


class ExperienceFormUpdate(BaseModel):
    model_config = _FORBID

    site_id: UUID | None = None
    page_id: UUID | None = None
    name: str | None = Field(default=None, max_length=255)
    description: str | None = None
    status: FormStatus | None = None
    form_schema_json: dict | None = None
    submit_action_json: dict | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class ExperienceFormRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID | None
    page_id: UUID | None
    code: str
    name: str
    description: str | None
    status: FormStatus
    form_schema_json: dict | None
    submit_action_json: dict | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class ExperienceFormListResponse(BaseModel):
    items: list[ExperienceFormRead]
    total: int
    page: int
    page_size: int


class FormSubmissionCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    form_id: UUID
    payload_json: dict | None = None
    crm_contact_ref: str | None = Field(default=None, max_length=255)
    communication_ref: str | None = Field(default=None, max_length=255)
    external_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None


class FormSubmissionUpdate(BaseModel):
    model_config = _FORBID

    status: FormSubmissionStatus | None = None
    crm_contact_ref: str | None = Field(default=None, max_length=255)
    communication_ref: str | None = Field(default=None, max_length=255)
    external_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class FormSubmissionRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    form_id: UUID
    status: FormSubmissionStatus
    payload_json: dict | None
    crm_contact_ref: str | None
    communication_ref: str | None
    external_ref: str | None
    submitted_at: datetime | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class FormSubmissionListResponse(BaseModel):
    items: list[FormSubmissionRead]
    total: int
    page: int
    page_size: int


class ExperienceSurveyCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID | None = None
    page_id: UUID | None = None
    code: str = Field(max_length=50)
    name: str = Field(max_length=255)
    description: str | None = None
    status: SurveyStatus = SurveyStatus.DRAFT
    questions_json: dict | None = None
    metadata_json: dict | None = None


class ExperienceSurveyUpdate(BaseModel):
    model_config = _FORBID

    site_id: UUID | None = None
    page_id: UUID | None = None
    name: str | None = Field(default=None, max_length=255)
    description: str | None = None
    status: SurveyStatus | None = None
    questions_json: dict | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class ExperienceSurveyRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID | None
    page_id: UUID | None
    code: str
    name: str
    description: str | None
    status: SurveyStatus
    questions_json: dict | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class ExperienceSurveyListResponse(BaseModel):
    items: list[ExperienceSurveyRead]
    total: int
    page: int
    page_size: int


class SurveyResponseCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    survey_id: UUID
    answers_json: dict | None = None
    crm_contact_ref: str | None = Field(default=None, max_length=255)
    external_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None


class SurveyResponseUpdate(BaseModel):
    model_config = _FORBID

    status: SurveyResponseStatus | None = None
    crm_contact_ref: str | None = Field(default=None, max_length=255)
    external_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class SurveyResponseRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    survey_id: UUID
    status: SurveyResponseStatus
    answers_json: dict | None
    crm_contact_ref: str | None
    external_ref: str | None
    submitted_at: datetime | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class SurveyResponseListResponse(BaseModel):
    items: list[SurveyResponseRead]
    total: int
    page: int
    page_size: int


class ExperienceAppointmentPageCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID
    page_id: UUID | None = None
    code: str = Field(max_length=50)
    name: str = Field(max_length=255)
    description: str | None = None
    status: AppointmentPageStatus = AppointmentPageStatus.DRAFT
    booking_provider_ref: str | None = Field(default=None, max_length=255)
    service_ref: str | None = Field(default=None, max_length=255)
    timezone: str | None = Field(default=None, max_length=64)
    availability_shell_json: dict | None = None
    metadata_json: dict | None = None


class ExperienceAppointmentPageUpdate(BaseModel):
    model_config = _FORBID

    page_id: UUID | None = None
    name: str | None = Field(default=None, max_length=255)
    description: str | None = None
    status: AppointmentPageStatus | None = None
    booking_provider_ref: str | None = Field(default=None, max_length=255)
    service_ref: str | None = Field(default=None, max_length=255)
    timezone: str | None = Field(default=None, max_length=64)
    availability_shell_json: dict | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class ExperienceAppointmentPageRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID
    page_id: UUID | None
    code: str
    name: str
    description: str | None
    status: AppointmentPageStatus
    booking_provider_ref: str | None
    service_ref: str | None
    timezone: str | None
    availability_shell_json: dict | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class ExperienceAppointmentPageListResponse(BaseModel):
    items: list[ExperienceAppointmentPageRead]
    total: int
    page: int
    page_size: int


class AppointmentBookingRefCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    appointment_page_id: UUID
    external_booking_ref: str = Field(max_length=255)
    status: AppointmentBookingStatus = AppointmentBookingStatus.PENDING
    crm_contact_ref: str | None = Field(default=None, max_length=255)
    slot_start: datetime | None = None
    slot_end: datetime | None = None
    metadata_json: dict | None = None


class AppointmentBookingRefUpdate(BaseModel):
    model_config = _FORBID

    status: AppointmentBookingStatus | None = None
    crm_contact_ref: str | None = Field(default=None, max_length=255)
    slot_start: datetime | None = None
    slot_end: datetime | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class AppointmentBookingRefRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    appointment_page_id: UUID
    external_booking_ref: str
    status: AppointmentBookingStatus
    crm_contact_ref: str | None
    slot_start: datetime | None
    slot_end: datetime | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class AppointmentBookingRefListResponse(BaseModel):
    items: list[AppointmentBookingRefRead]
    total: int
    page: int
    page_size: int
