from __future__ import annotations

import asyncio
from sqlmodel import select

from app.db import async_session_factory
from app.models.entities import Poll, PollStatus
from app.routers.ws import broadcast_room_snapshot
from app.services.voting import close_poll_and_set_winner
from app.services.time_utils import utc_now


async def close_expired_polls_once() -> int:
    now = utc_now()
    async with async_session_factory() as session:
        result = await session.exec(
            select(Poll).where(
                Poll.status == PollStatus.open,
                Poll.deadline_at.is_not(None),
                Poll.deadline_at <= now,
            )
        )
        polls = list(result.all())
        if not polls:
            return 0
        touched_rooms: set[str] = set()
        for poll in polls:
            await close_poll_and_set_winner(session, poll)
            touched_rooms.add(poll.room_id)
        await session.commit()

    for room_id in touched_rooms:
        await broadcast_room_snapshot(room_id)
    return len(polls)


async def scheduler_loop(stop_event: asyncio.Event, interval_seconds: float = 1.0) -> None:
    while not stop_event.is_set():
        try:
            await close_expired_polls_once()
        except Exception:
            # Keep scheduler alive in MVP mode.
            pass
        try:
            await asyncio.wait_for(stop_event.wait(), timeout=interval_seconds)
        except asyncio.TimeoutError:
            continue
