"""Модель сообщения чата — текстовый чат в конференции (WS).

Автор — зарегистрированный пользователь ИЛИ гость (ровно один из `user_id`/
`guest_access_id` заполнен, аналогично `ConferenceParticipant` из ADR-001,
п.6). `author_name` — снапшот отображаемого имени из LiveKit access-токена
на момент отправки сообщения: не связан жёстко с текущим именем
пользователя/гостя, переживает их последующее переименование или удаление
гостевой записи (`ON DELETE CASCADE` у `guest_access_id` относится к самому
сообщению, а не к отображаемому имени в истории чата).
"""

import uuid
from datetime import datetime

from sqlalchemy import (
    BigInteger,
    CheckConstraint,
    DateTime,
    ForeignKey,
    Identity,
    Index,
    String,
    Text,
    func,
)
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column

from models.base import Base


class ChatMessage(Base):
    """Одно сообщение чата, опубликованное в конференции."""

    __tablename__ = "chat_messages"
    __table_args__ = (
        Index("ix_chat_messages_session_id_created_at", "session_id", "created_at"),
        CheckConstraint(
            "user_id IS NOT NULL OR guest_access_id IS NOT NULL",
            name="ck_chat_messages_author",
        ),
    )

    id: Mapped[int] = mapped_column(BigInteger, Identity(always=True), primary_key=True)
    session_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("conference_sessions.id", ondelete="CASCADE"),
        nullable=False,
    )
    user_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("users.id"), nullable=True
    )
    guest_access_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("guest_access.id", ondelete="CASCADE"), nullable=True
    )
    author_name: Mapped[str] = mapped_column(String(255), nullable=False)
    text: Mapped[str] = mapped_column(Text, nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, server_default=func.now()
    )
