"""Module-level holder for the uvicorn Server and TrayManager references.

Allows the shutdown API endpoint to trigger graceful shutdown via
``server.should_exit = True`` + ``tray.stop()``, which is the same
mechanism the system tray "Shutdown" menu item uses.
"""

from typing import Any, Optional

from wled_controller.utils import get_logger

logger = get_logger(__name__)

_server: Optional[Any] = None  # uvicorn.Server
_tray: Optional[Any] = None    # TrayManager


def set_server(server: Any) -> None:
    """Store the uvicorn Server instance (called from __main__)."""
    global _server
    _server = server


def set_tray(tray: Any) -> None:
    """Store the TrayManager instance (called from __main__)."""
    global _tray
    _tray = tray


def request_shutdown() -> None:
    """Signal uvicorn + tray to perform a graceful shutdown.

    Broadcasts a ``server_restarting`` event so the frontend can show
    a restart indicator, persists all stores to disk, then sets
    ``should_exit = True`` on the uvicorn Server and stops the tray.
    """
    # Notify connected clients that a restart is in progress
    _broadcast_restarting()

    # Persist stores before signaling shutdown.
    # The lifespan shutdown handler also saves, but it may not run
    # reliably when uvicorn is in a daemon thread.
    try:
        from wled_controller.main import _save_all_stores
        _save_all_stores()
    except Exception as e:
        logger.debug("Best-effort store save on shutdown failed: %s", e)
        pass  # best-effort; lifespan handler is the backup

    if _server is not None:
        _server.should_exit = True
    if _tray is not None:
        _tray.stop()


def _broadcast_restarting() -> None:
    """Push a server_restarting event to all connected WebSocket clients."""
    try:
        from wled_controller.api.dependencies import _deps
        pm = _deps.get("processor_manager")
        if pm is not None:
            pm.fire_event({"type": "server_restarting"})
    except Exception as e:
        logger.debug("Failed to broadcast server_restarting event: %s", e)
        pass
