"""Inbound queue + rate limiting for mesh messages."""
from __future__ import annotations

import asyncio
import time
from collections import deque
from dataclasses import dataclass
from typing import Any


@dataclass
class QueueAdmission:
    ok: bool
    status_code: int
    payload: dict[str, Any]


class MeshInboundQueue:
    def __init__(self, maxsize: int = 100, rate_limit_per_minute: int = 20):
        self.queue: asyncio.Queue[dict[str, Any]] = asyncio.Queue(maxsize=maxsize)
        self.rate_limit_per_minute = max(1, int(rate_limit_per_minute))
        self._arrival_times: deque[float] = deque()
        self.user_active: bool = False

    def set_user_active(self, active: bool) -> None:
        self.user_active = bool(active)

    def _prune(self) -> None:
        now = time.time()
        while self._arrival_times and (now - self._arrival_times[0]) > 60.0:
            self._arrival_times.popleft()

    def admit(self) -> QueueAdmission:
        self._prune()
        if len(self._arrival_times) >= self.rate_limit_per_minute:
            return QueueAdmission(
                ok=False,
                status_code=429,
                payload={
                    "status": "busy",
                    "retry_after_seconds": 30,
                    "message": "This Mugi instance is busy at the moment. Please try again shortly.",
                    "queue_depth": self.queue.qsize(),
                },
            )
        if self.queue.full():
            return QueueAdmission(
                ok=False,
                status_code=503,
                payload={
                    "status": "busy",
                    "retry_after_seconds": 45,
                    "message": "This Mugi instance queue is full right now. Please try again shortly.",
                    "queue_depth": self.queue.qsize(),
                },
            )
        self._arrival_times.append(time.time())
        return QueueAdmission(ok=True, status_code=200, payload={"ok": True})

    async def put(self, item: dict[str, Any]) -> None:
        await self.queue.put(item)

    async def get(self) -> dict[str, Any]:
        return await self.queue.get()
