import asyncio
import json

from fastapi import APIRouter
from fastapi.responses import StreamingResponse
from sqlalchemy import desc
from sqlmodel import select

from app.db import async_session_factory
from app.models.entities import Poll, PollStatus
from app.routers.polls import poll_out
from app.services import participants as participants_svc
from app.services import voting as voting_svc

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


async def build_room_snapshot(room_id: str) -> dict:
    async with async_session_factory() as session:
        result = await session.exec(
            select(Poll).where(Poll.room_id == room_id).order_by(desc(Poll.created_at))
        )
        rows = list(result.all())
        all_polls = [poll_out(p) for p in rows]
        target = (
            next((p for p in rows if p.status == PollStatus.open), None)
            or next((p for p in rows if p.status == PollStatus.closed), None)
            or next((p for p in rows if p.status == PollStatus.draft), None)
        )
        participant_count = await participants_svc.count_room_active_participants(session, room_id)
        active_session_count = await participants_svc.count_room_sessions(session, room_id)
        if not target:
            return {
                "room_id": room_id,
                "room": {
                    "id": room_id,
                    "participant_count": participant_count,
                    "active_session_count": active_session_count,
                },
                "poll": None,
                "polls": all_polls,
                "stats": None,
                "controller": None,
            }
        tally = await voting_svc.compute_tally(session, target.id)
        opts = voting_svc.parse_options(target)
        for o in opts:
            tally.setdefault(o, 0)
        leader, tie = voting_svc.pick_winner(tally, opts)
        runtime = voting_svc.parse_poll_runtime(target)
        return {
            "room_id": room_id,
            "room": {
                "id": room_id,
                "participant_count": participant_count,
                "active_session_count": active_session_count,
            },
            "poll": poll_out(target),
            "polls": all_polls,
            "stats": {
                "counts": tally,
                "total": sum(tally.values()),
                "leader": leader,
                "tie": tie,
            },
            "controller": runtime.get("controller_command"),
        }


@router.get("/stream/room/{room_id}")
async def stream_room(room_id: str):
    # SSE is kept as a development fallback. Primary realtime path is WebSocket.
    async def event_gen():
        while True:
            snap = await build_room_snapshot(room_id)
            yield f"data: {json.dumps(snap, default=str)}\n\n"
            await asyncio.sleep(1)

    return StreamingResponse(event_gen(), media_type="text/event-stream")


@router.get("/rooms/{room_id}/snapshot")
async def get_room_snapshot(room_id: str):
    return await build_room_snapshot(room_id)
