"""Watch gets Codex quota on startup, even when the selected agent is Pi."""
import asyncio
import logging

import device_gateway.app as gateway
from device_gateway.control.codex_quota import INVALID, normalize


class Adapter:
    def __init__(self, fail=False):
        self.started = asyncio.Event()
        self.release = asyncio.Event()
        self.finished = asyncio.Event()
        self.fail = fail
        self.quota = INVALID
        self.reads = 0
        self.cancelled = False

    async def ready(self):
        self.reads += 1
        self.started.set()
        try:
            await self.release.wait()
            if self.fail:
                raise RuntimeError("provider unavailable")
            self.quota = normalize({"rateLimits": {"primary": {"usedPercent": 28}}})
        except asyncio.CancelledError:
            self.cancelled = True
            raise
        finally:
            self.finished.set()

    async def close(self):
        assert self.finished.is_set()


def test_lifespan_warms_quota_without_blocking_startup(monkeypatch):
    async def scenario():
        adapter = Adapter()
        monkeypatch.setattr(gateway, "adapters", {"codex": adapter})
        async with gateway.lifespan(gateway.app):
            # Entering lifespan succeeds before the provider responds.
            await asyncio.wait_for(adapter.started.wait(), 1)
            assert not adapter.finished.is_set()
            assert gateway.device_snapshot_payload(gateway.system_collector.collect())["codex_quota_valid"] is False
            adapter.release.set()
            await asyncio.wait_for(adapter.finished.wait(), 1)
            payload = gateway.device_snapshot_payload(gateway.system_collector.collect())
            assert payload["codex_quota_valid"] is True
            assert payload["codex_remaining_percent"] == 72
            await asyncio.sleep(0)
            assert adapter.reads == 1

    asyncio.run(scenario())


def test_startup_failure_does_not_stop_gateway(monkeypatch, caplog):
    async def scenario():
        adapter = Adapter(fail=True)
        adapter.release.set()
        monkeypatch.setattr(gateway, "adapters", {"codex": adapter})
        async with gateway.lifespan(gateway.app):
            await asyncio.wait_for(adapter.finished.wait(), 1)
            assert adapter.quota == INVALID

    with caplog.at_level(logging.WARNING):
        asyncio.run(scenario())
    assert "Codex quota initialization unavailable" in caplog.text


def test_shutdown_cancels_initialization_before_closing_adapter(monkeypatch):
    async def scenario():
        adapter = Adapter()
        monkeypatch.setattr(gateway, "adapters", {"codex": adapter})
        async with gateway.lifespan(gateway.app):
            await asyncio.wait_for(adapter.started.wait(), 1)
        assert adapter.cancelled

    asyncio.run(scenario())


def test_codex_disabled_creates_no_startup_task(monkeypatch):
    async def scenario():
        monkeypatch.setattr(gateway, "adapters", {})
        async with gateway.lifespan(gateway.app):
            assert not any(task.get_name() == "codex-quota-initialize"
                           for task in asyncio.all_tasks())

    asyncio.run(scenario())
