"""Permission request service for managing tool permission requests and decisions.

Provides an in-memory store for pending permission requests and persists
session-scoped decisions (allow-always / reject-always) so that repeated
requests from the same tool are handled automatically.
"""

from __future__ import annotations

from collections import OrderedDict

from cleveragents.tui.permissions.models import (
    PermissionDecision,
    ToolPermissionRequest,
)

__all__ = ["PermissionRequestService"]


class PermissionRequestService:
    """Manages tool permission requests and session-scoped decisions.

    * Queues incoming ``ToolPermissionRequest`` objects.
    * Records ``allow_always`` / ``reject_always`` decisions so that
      subsequent requests from the same tool are auto-resolved.
    * Provides iteration over pending requests.
    """

    def __init__(self) -> None:
        # Ordered dict preserves insertion order for queue semantics.
        self._requests: OrderedDict[str, ToolPermissionRequest] = OrderedDict()
        # Maps tool_name -> PermissionDecision for session-scoped decisions.
        self._session_decisions: dict[str, PermissionDecision] = {}

    # ── Queue management ──────────────────────────────────────────

    def enqueue(self, request: ToolPermissionRequest) -> None:
        """Add a new permission request to the queue.

        If a session-scoped decision already exists for the tool, the
        request is auto-resolved immediately and stored with that decision.
        """
        session_decision = self._session_decisions.get(request.tool_name)
        if session_decision is not None:
            request = request.apply_decision(session_decision)
        self._requests[request.request_id] = request

    def get(self, request_id: str) -> ToolPermissionRequest | None:
        """Return the request with the given ID, or None."""
        return self._requests.get(request_id)

    def pending_requests(self) -> list[ToolPermissionRequest]:
        """Return all requests that have not yet been decided."""
        return [r for r in self._requests.values() if r.is_pending]

    def all_requests(self) -> list[ToolPermissionRequest]:
        """Return all requests (pending and decided)."""
        return list(self._requests.values())

    # ── Decision recording ────────────────────────────────────────

    def record_decision(
        self,
        request_id: str,
        decision: PermissionDecision,
    ) -> ToolPermissionRequest | None:
        """Apply *decision* to the request identified by *request_id*.

        If the decision is ``allow_always`` or ``reject_always``, the
        tool name is recorded in the session-scoped decision map so that
        future requests from the same tool are auto-resolved.

        Returns the updated request, or ``None`` if not found.
        """
        request = self._requests.get(request_id)
        if request is None:
            return None

        updated = request.apply_decision(decision)
        self._requests[request_id] = updated

        if decision in {
            PermissionDecision.ALLOW_ALWAYS,
            PermissionDecision.REJECT_ALWAYS,
        }:
            self._session_decisions[request.tool_name] = decision

        return updated

    def get_session_decision(self, tool_name: str) -> PermissionDecision | None:
        """Return the session-scoped decision for *tool_name*, or None."""
        return self._session_decisions.get(tool_name)

    def clear_session_decision(self, tool_name: str) -> bool:
        """Remove the session-scoped decision for *tool_name*.

        Returns True if a decision was removed, False if none existed.
        """
        if tool_name in self._session_decisions:
            del self._session_decisions[tool_name]
            return True
        return False

    def clear_all(self) -> None:
        """Clear all requests and session decisions."""
        self._requests.clear()
        self._session_decisions.clear()
