"""
System WebSocket message schemas.

Provides typed messages for system-level WebSocket operations including:
- Ping/pong for keepalive
- Health checks
- Maintenance notifications
- System broadcasts

Usage:
    from lightwave.schema.pydantic.contracts.websockets.system import (
        SystemPingInbound,
        SystemPongOutbound,
        SystemMaintenanceOutbound,
    )

    # Respond to ping
    pong = SystemPongOutbound(
        echo=ping.timestamp,
        server_time=datetime.utcnow(),
    )
    await websocket.send(pong.to_ws_json())
"""

from datetime import datetime
from typing import Literal

from pydantic import Field

from lightwave.schema.pydantic.contracts.websockets.base import WSMessage

# =============================================================================
# Subscribe
# =============================================================================


class SystemSubscribeInbound(WSMessage):
    """
    Subscribe to system events.

    Allows clients to opt-in to specific system event types.
    """

    type: Literal["system.subscribe"] = "system.subscribe"
    event_types: list[Literal["health", "maintenance", "broadcast"]] = Field(
        ...,
        description="Event types to subscribe to",
    )


# =============================================================================
# Ping/Pong (Keepalive)
# =============================================================================


class SystemPingInbound(WSMessage):
    """
    Client ping for keepalive.

    Sent periodically to keep connection alive and measure latency.
    """

    type: Literal["system.ping"] = "system.ping"
    client_time: datetime | None = Field(
        None,
        description="Client timestamp for latency measurement",
    )


class SystemPongOutbound(WSMessage):
    """
    Server pong response.

    Sent in response to client ping.
    """

    type: Literal["system.pong"] = "system.pong"
    echo: datetime | None = Field(
        None,
        description="Echo of client_time from ping",
    )
    server_time: datetime = Field(
        default_factory=datetime.utcnow,
        description="Server timestamp",
    )


# =============================================================================
# Health Check
# =============================================================================


class SystemHealthOutbound(WSMessage):
    """
    System health status.

    Sent periodically or on request to indicate system status.
    """

    type: Literal["system.health"] = "system.health"
    status: Literal["healthy", "degraded", "unhealthy"] = Field(
        ...,
        description="Overall system status",
    )
    services: dict[str, bool] | None = Field(
        None,
        description="Individual service statuses",
    )
    latency_ms: int | None = Field(
        None,
        description="Current server latency in ms",
    )


# =============================================================================
# Maintenance
# =============================================================================


class SystemMaintenanceOutbound(WSMessage):
    """
    Maintenance notification.

    Sent to warn clients of upcoming or ongoing maintenance.
    """

    type: Literal["system.maintenance"] = "system.maintenance"
    status: Literal["scheduled", "starting", "in_progress", "completed"] = Field(
        ...,
        description="Maintenance status",
    )
    message: str = Field(..., description="Human-readable message")
    starts_at: datetime | None = Field(None, description="When maintenance starts")
    ends_at: datetime | None = Field(None, description="Expected end time")
    disconnect_in_seconds: int | None = Field(
        None,
        description="Seconds until forced disconnect (if applicable)",
    )


# =============================================================================
# Broadcast
# =============================================================================


class SystemBroadcastOutbound(WSMessage):
    """
    System-wide broadcast message.

    Sent to all connected clients (e.g., announcements, alerts).
    """

    type: Literal["system.broadcast"] = "system.broadcast"
    title: str = Field(..., max_length=200, description="Broadcast title")
    message: str = Field(..., max_length=2000, description="Broadcast content")
    severity: Literal["info", "warning", "critical"] = Field(
        "info",
        description="Message severity",
    )
    action_url: str | None = Field(None, description="Optional action link")
    dismissible: bool = Field(True, description="Whether user can dismiss")
    expires_at: datetime | None = Field(None, description="When message expires")
