"""Pydantic-схемы событий комнаты, мультиплексируемых поверх WS-чата (`api/chat.py`).

Отдельный протокол от собственно чата (`schemas/chat.py`): очередь поднятых
рук и уведомления о принудительном мьюте — эфемерное состояние звонка
(Redis, не БД, см. `services/hand_queue.py`) и не должны попадать в
персистентную историю сообщений чата, хотя и едут по тому же соединению.
"""

from datetime import UTC, datetime
from typing import Literal

from pydantic import BaseModel, Field, field_serializer


class RaiseHandIn(BaseModel):
    """Клиент поднимает свою руку."""

    type: Literal["raise_hand"]


class LowerHandIn(BaseModel):
    """Клиент опускает руку — свою (без `identity`) либо, только для организатора, чужую."""

    type: Literal["lower_hand"]
    identity: str | None = None


class HandQueueEntryOut(BaseModel):
    """Один участник в очереди поднятых рук."""

    identity: str
    name: str
    raised_at: datetime

    @field_serializer("raised_at")
    def _serialize_raised_at(self, value: datetime) -> str:
        return value.astimezone(UTC).isoformat().replace("+00:00", "Z")


class HandQueueOut(BaseModel):
    """Снапшот очереди поднятых рук — рассылается всем участникам при любом изменении."""

    type: Literal["hand_queue"] = "hand_queue"
    queue: list[HandQueueEntryOut] = Field(default_factory=list)


ForcedMuteSource = Literal["microphone", "camera"]


class ForcedMuteOut(BaseModel):
    """Организатор принудительно выключил трек участника (задача B2) — уведомление всем.

    Рассылается всем (не только затронутому), как и `HandQueueOut`: канал —
    общий broadcast, а не адресная доставка одному соединению; получатели,
    для которых `identity` не совпадает с их собственной, событие
    игнорируют.
    """

    type: Literal["forced_mute"] = "forced_mute"
    identity: str
    source: ForcedMuteSource
