"""Модель Conference — конференция как пользовательская сущность (ADR-001).

Конференция — постоянная сущность с номером и ссылкой; каждый её запуск
порождает отдельную запись `ConferenceSession` (см. `models/session.py`),
которая и является единицей AI-пайплайна пост-обработки.
"""

import uuid
from datetime import datetime
from typing import Any

from sqlalchemy import (
    Boolean,
    CheckConstraint,
    DateTime,
    Enum,
    ForeignKey,
    Integer,
    String,
    Text,
    func,
    text,
)
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column

from models.base import Base

# Жизненный цикл конференции (ADR-001, п.2): `draft` не нужен — создание
# атомарно из формы; `is_pinned` — ортогональный флаг, а не статус.
ConferenceStatus = Enum(
    "scheduled",
    "active",
    "ended",
    name="conference_status",
)


class Conference(Base):
    """Конференция — номер, постоянная ссылка, владелец, признаки закрепления/закрытости."""

    __tablename__ = "conferences"
    __table_args__ = (
        CheckConstraint(
            "is_closed = false OR password_hash IS NOT NULL",
            name="ck_conferences_closed_requires_password",
        ),
        CheckConstraint(
            "recurrence IS NULL OR is_pinned = true",
            name="ck_conferences_recurrence_requires_pinned",
        ),
        CheckConstraint(
            "summary_recipients IN ('all', 'owner')",
            name="ck_conferences_summary_recipients",
        ),
    )

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, server_default=text("gen_random_uuid()")
    )
    # 9 десятичных цифр, первая 1..9 (services/conference_ids.py::generate_number).
    number: Mapped[str] = mapped_column(String(9), unique=True, nullable=False)
    # secrets.token_urlsafe(8) — 11 base64url-символов (services/conference_ids.py::generate_slug).
    slug: Mapped[str] = mapped_column(String(22), unique=True, nullable=False)
    title: Mapped[str | None] = mapped_column(String(255), nullable=True)
    owner_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
    )
    status: Mapped[str] = mapped_column(
        ConferenceStatus, nullable=False, server_default="scheduled"
    )
    is_pinned: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default="false")
    is_closed: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default="false")
    password_hash: Mapped[str | None] = mapped_column(Text, nullable=True)
    scheduled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    duration_minutes: Mapped[int | None] = mapped_column(Integer, nullable=True)
    # Pydantic-модель RecurrenceRule (services/recurrence.py), сериализованная в JSONB.
    recurrence: Mapped[dict[str, Any] | None] = mapped_column(JSONB, nullable=True)
    ended_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    # Переопределение рассылки саммари конкретной конференции;
    # NULL = использовать дефолт инстанса (`instance_settings['summary_recipients']`).
    summary_recipients: Mapped[str | None] = mapped_column(String(16), nullable=True)
    # Счётчик изменений расписания для VEVENT `SEQUENCE` (.ics):
    # растёт при правке `scheduled_at`/`duration_minutes`/`recurrence`/`title`,
    # чтобы календарные клиенты обновляли уже принятое приглашение по UID.
    ics_sequence: Mapped[int] = mapped_column(Integer, nullable=False, server_default="0")
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, server_default=func.now()
    )
