"""
Classroom API - WebSocket Routes

Real-time WebSocket endpoints for timer updates.
"""

import json
from typing import Dict, Any
from datetime import datetime
import logging

from fastapi import APIRouter, WebSocket, WebSocketDisconnect

from ..services.persistence import (
    sessions,
    init_db_if_needed,
    DB_ENABLED,
    SessionLocal,
)
from ..websocket_manager import (
    ws_manager,
    start_timer_broadcast,
    build_timer_status,
    is_timer_broadcast_running,
)

logger = logging.getLogger(__name__)

router = APIRouter(tags=["WebSocket"])


@router.websocket("/ws/{session_id}")
async def websocket_timer(websocket: WebSocket, session_id: str):
    """
    WebSocket-Endpoint fuer Echtzeit-Timer-Updates.

    Features:
    - Sub-Sekunden Timer-Updates (jede Sekunde)
    - Phasenwechsel-Benachrichtigungen
    - Session-Ende-Benachrichtigungen
    - Multi-Device Support

    Protocol:
    - Server sendet JSON-Messages mit "type" und "data"
    - Types: "timer_update", "phase_change", "session_ended", "error", "connected"
    - Client kann "ping" senden fuer Keepalive
    """
    # Session validieren bevor Connect
    session = sessions.get(session_id)
    if not session:
        # Versuche aus DB zu laden
        if DB_ENABLED:
            try:
                init_db_if_needed()
                from classroom_engine.repository import SessionRepository
                db = SessionLocal()
                repo = SessionRepository(db)
                db_session = repo.get_by_id(session_id)
                if db_session:
                    session = repo.to_dataclass(db_session)
                    sessions[session_id] = session
                db.close()
            except Exception as e:
                logger.error(f"WebSocket: Failed to load session {session_id}: {e}")

    if not session:
        await websocket.close(code=4004, reason="Session not found")
        return

    if session.is_ended:
        await websocket.close(code=4001, reason="Session already ended")
        return

    # Verbindung akzeptieren und registrieren
    await ws_manager.connect(websocket, session_id)

    # Timer-Broadcast-Task starten wenn noetig
    start_timer_broadcast(sessions)

    # Initiale Daten senden
    try:
        initial_timer = build_timer_status(session)
        await websocket.send_json({
            "type": "connected",
            "data": {
                "session_id": session_id,
                "client_count": ws_manager.get_client_count(session_id),
                "timer": initial_timer
            }
        })
    except Exception as e:
        logger.error(f"WebSocket: Failed to send initial data: {e}")

    # Message-Loop
    try:
        while True:
            try:
                message = await websocket.receive_text()
                data = json.loads(message)

                if data.get("type") == "ping":
                    await websocket.send_json({"type": "pong"})
                elif data.get("type") == "get_timer":
                    # Client kann manuell Timer-Status anfordern
                    session = sessions.get(session_id)
                    if session and not session.is_ended:
                        timer_data = build_timer_status(session)
                        await websocket.send_json({
                            "type": "timer_update",
                            "data": timer_data
                        })
            except json.JSONDecodeError:
                await websocket.send_json({
                    "type": "error",
                    "data": {"message": "Invalid JSON"}
                })
    except WebSocketDisconnect:
        logger.info(f"WebSocket: Client disconnected from session {session_id}")
    except Exception as e:
        logger.error(f"WebSocket error: {e}")
    finally:
        await ws_manager.disconnect(websocket)


@router.get("/ws/status")
async def websocket_status() -> Dict[str, Any]:
    """
    Status-Endpoint fuer WebSocket-Verbindungen.

    Zeigt aktive Sessions und Verbindungszahlen.
    """
    active_sessions = ws_manager.get_active_sessions()
    return {
        "active_sessions": len(active_sessions),
        "sessions": [
            {
                "session_id": sid,
                "client_count": ws_manager.get_client_count(sid)
            }
            for sid in active_sessions
        ],
        "broadcast_task_running": is_timer_broadcast_running()
    }
