"""Tower dashboard — real-time Spark visualization via WebSocket.

GET  /tower     — HTML Tower dashboard (Thinking / Predicting / Advising)
WS   /tower/ws  — WebSocket stream of Spark engine state updates
"""

import asyncio
import json
import logging

from fastapi import APIRouter, Request, WebSocket
from fastapi.responses import HTMLResponse

from dashboard.templating import templates
from spark.engine import spark_engine

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/tower", tags=["tower"])

_PUSH_INTERVAL = 5  # seconds between state broadcasts


def _spark_snapshot() -> dict:
    """Build a JSON-serialisable snapshot of Spark state."""
    status = spark_engine.status()

    timeline = spark_engine.get_timeline(limit=10)
    events = []
    for ev in timeline:
        entry = {
            "event_type": ev.event_type,
            "description": ev.description,
            "importance": ev.importance,
            "created_at": ev.created_at,
        }
        if ev.agent_id:
            entry["agent_id"] = ev.agent_id[:8]
        if ev.task_id:
            entry["task_id"] = ev.task_id[:8]
        try:
            entry["data"] = json.loads(ev.data)
        except (json.JSONDecodeError, TypeError):
            entry["data"] = {}
        events.append(entry)

    predictions = spark_engine.get_predictions(limit=5)
    preds = []
    for p in predictions:
        pred = {
            "task_id": p.task_id[:8] if p.task_id else "?",
            "accuracy": p.accuracy,
            "evaluated": p.evaluated_at is not None,
            "created_at": p.created_at,
        }
        try:
            pred["predicted"] = json.loads(p.predicted_value)
        except (json.JSONDecodeError, TypeError):
            pred["predicted"] = {}
        preds.append(pred)

    advisories = spark_engine.get_advisories()
    advs = [
        {
            "category": a.category,
            "priority": a.priority,
            "title": a.title,
            "detail": a.detail,
            "suggested_action": a.suggested_action,
        }
        for a in advisories
    ]

    return {
        "type": "spark_state",
        "status": status,
        "events": events,
        "predictions": preds,
        "advisories": advs,
    }


@router.get("", response_class=HTMLResponse)
async def tower_ui(request: Request):
    """Render the Tower dashboard page."""
    snapshot = _spark_snapshot()
    return templates.TemplateResponse(
        request,
        "tower.html",
        {"snapshot": snapshot},
    )


@router.websocket("/ws")
async def tower_ws(websocket: WebSocket) -> None:
    """Stream Spark state snapshots to the Tower dashboard."""
    await websocket.accept()
    logger.info("Tower WS connected")

    try:
        # Send initial snapshot
        await websocket.send_text(json.dumps(_spark_snapshot()))

        while True:
            await asyncio.sleep(_PUSH_INTERVAL)
            await websocket.send_text(json.dumps(_spark_snapshot()))
    except Exception:
        logger.debug("Tower WS disconnected")
