"""
Helper functions to build and broadcast typed WebSocket events.
Import `manager` and call broadcast_* helpers from service methods.
"""
from datetime import datetime, timezone
from typing import Any

from app.realtime.manager import manager
from app.schemas.ws_event import WsEvent, WsEventType


def _now() -> str:
    return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")


def _make(event_type: WsEventType, canal: str, payload: dict[str, Any]) -> dict:
    return WsEvent(type=event_type, canal=canal, payload=payload).model_dump()


# ── Signalements ──────────────────────────────────────────────────────────────

async def broadcast_signalement_created(signalement_id: str, payload: dict) -> None:
    event = _make(WsEventType.SIGNALEMENT_CREATED, "signalements", payload)
    await manager.broadcast("signalements", event)


async def broadcast_statut_updated(signalement_id: str, payload: dict) -> None:
    event = _make(WsEventType.SIGNALEMENT_STATUT_UPDATED, f"signalement:{signalement_id}", payload)
    await manager.broadcast(f"signalement:{signalement_id}", event)
    await manager.broadcast("signalements", event)


async def broadcast_signalement_assigned(signalement_id: str, payload: dict) -> None:
    event = _make(WsEventType.SIGNALEMENT_ASSIGNED, f"signalement:{signalement_id}", payload)
    await manager.broadcast(f"signalement:{signalement_id}", event)
    await manager.broadcast("signalements", event)


async def broadcast_note_added(signalement_id: str, payload: dict) -> None:
    event = _make(WsEventType.SIGNALEMENT_NOTE_ADDED, f"signalement:{signalement_id}", payload)
    await manager.broadcast(f"signalement:{signalement_id}", event)


# ── Messages ──────────────────────────────────────────────────────────────────

async def broadcast_message_created(discussion_id: str, payload: dict) -> None:
    event = _make(WsEventType.MESSAGE_CREATED, f"discussion:{discussion_id}", payload)
    await manager.broadcast(f"discussion:{discussion_id}", event)


async def broadcast_message_read(discussion_id: str, payload: dict) -> None:
    event = _make(WsEventType.MESSAGE_READ, f"discussion:{discussion_id}", payload)
    await manager.broadcast(f"discussion:{discussion_id}", event)


async def broadcast_discussion_created(payload: dict) -> None:
    event = _make(WsEventType.DISCUSSION_CREATED, "discussions", payload)
    await manager.broadcast("discussions", event)


async def broadcast_user_typing(discussion_id: str, user_id: str, user_name: str, is_typing: bool) -> None:
    event = _make(
        WsEventType.USER_TYPING,
        f"discussion:{discussion_id}",
        {"userId": user_id, "userName": user_name, "isTyping": is_typing}
    )
    await manager.broadcast(f"discussion:{discussion_id}", event)


# ── Postes (Forum) ────────────────────────────────────────────────────────────

async def broadcast_poste_created(poste_id: str, payload: dict) -> None:
    event = _make(WsEventType.POSTE_CREATED, f"poste:{poste_id}", payload)
    await manager.broadcast(f"poste:{poste_id}", event)
    await manager.broadcast("postes", event)


async def broadcast_poste_updated(poste_id: str, payload: dict) -> None:
    event = _make(WsEventType.POSTE_UPDATED, f"poste:{poste_id}", payload)
    await manager.broadcast(f"poste:{poste_id}", event)
    await manager.broadcast("postes", event)


async def broadcast_poste_deleted(poste_id: str) -> None:
    event = _make(WsEventType.POSTE_DELETED, "postes", {"id": poste_id})
    await manager.broadcast("postes", event)


async def broadcast_commentaire_created(poste_id: str, payload: dict) -> None:
    event = _make(WsEventType.COMMENTAIRE_CREATED, f"poste:{poste_id}", payload)
    await manager.broadcast(f"poste:{poste_id}", event)
    await manager.broadcast("postes", event)


async def broadcast_reaction_created(poste_id: str, payload: dict) -> None:
    event = _make(WsEventType.REACTION_CREATED, f"poste:{poste_id}", payload)
    await manager.broadcast(f"poste:{poste_id}", event)
    await manager.broadcast("postes", event)


async def broadcast_reaction_removed(poste_id: str, payload: dict) -> None:
    event = _make(WsEventType.REACTION_REMOVED, f"poste:{poste_id}", payload)
    await manager.broadcast(f"poste:{poste_id}", event)
    await manager.broadcast("postes", event)


# ── Calendriers ───────────────────────────────────────────────────────────────

async def broadcast_event_created(payload: dict) -> None:
    event = _make(WsEventType.EVENT_CREATED, "calendriers", payload)
    await manager.broadcast("calendriers", event)


async def broadcast_event_updated(payload: dict) -> None:
    event = _make(WsEventType.EVENT_UPDATED, "calendriers", payload)
    await manager.broadcast("calendriers", event)


async def broadcast_event_cancelled(payload: dict) -> None:
    event = _make(WsEventType.EVENT_CANCELLED, "calendriers", payload)
    await manager.broadcast("calendriers", event)


# ── Dashboard ─────────────────────────────────────────────────────────────────

async def broadcast_stats_updated(payload: dict) -> None:
    event = _make(WsEventType.STATS_UPDATED, "dashboard", payload)
    await manager.broadcast("dashboard", event)


async def broadcast_home_summary_updated(payload: dict) -> None:
    event = _make(WsEventType.STATS_UPDATED, "home", payload)
    await manager.broadcast("home", event)


# ── Admin ─────────────────────────────────────────────────────────────────────

async def broadcast_system_alert(payload: dict) -> None:
    event = _make(WsEventType.SYSTEM_ALERT, "admin", payload)
    await manager.broadcast("admin", event)


async def broadcast_user_deactivated(user_id: str, payload: dict) -> None:
    event = _make(WsEventType.USER_DEACTIVATED, "admin", payload)
    await manager.broadcast("admin", event)
    await manager.broadcast_to_user(user_id, event)
