"""SSE handler for OIDC device authentication."""

import asyncio
from aiohttp import web
from homeassistant.components.http import HomeAssistantView
from ..provider import OpenIDAuthProvider
from ..tools.helpers import get_valid_state_id

PATH = "/auth/oidc/device-sse"


class OIDCDeviceSSE(HomeAssistantView):
    """OIDC Plugin SSE Handler."""

    requires_auth = False
    url = PATH
    name = "auth:oidc:device-sse"

    def __init__(self, oidc_provider: OpenIDAuthProvider) -> None:
        self.oidc_provider = oidc_provider

    async def get(self, req: web.Request) -> web.Response:
        """Check for mobile sign-in completion with short server-side polling."""
        state_id = await get_valid_state_id(req, self.oidc_provider)
        if not state_id:
            raise web.HTTPBadRequest(text="Missing session cookie")

        timeout_seconds = 300
        started_at = asyncio.get_running_loop().time()

        response = web.StreamResponse(
            status=200,
            headers={
                "Content-Type": "text/event-stream",
                "Cache-Control": "no-cache",
                "Connection": "keep-alive",
            },
        )
        await response.prepare(req)

        try:
            while True:
                if (
                    await self.oidc_provider.async_get_redirect_uri_for_state(state_id)
                    is None
                ):
                    await response.write(b"event: expired\ndata: false\n\n")
                    break

                ready = await self.oidc_provider.async_is_state_ready(state_id)
                if ready:
                    await response.write(b"event: ready\ndata: true\n\n")
                    break

                if asyncio.get_running_loop().time() - started_at >= timeout_seconds:
                    await response.write(b"event: timeout\ndata: false\n\n")
                    break

                await response.write(b"event: waiting\ndata: false\n\n")
                await asyncio.sleep(0.5)
        except (ConnectionResetError, RuntimeError):
            # Client disconnected while listening for state changes.
            pass
        finally:
            try:
                await response.write_eof()
            except ConnectionResetError:
                pass

        return response
