"""RBAC middleware for FastAPI -- enforces team plan access control.

Checks: Is RBAC enabled? Who is the requester? What model? Do they have access?
Uses API key from Authorization header to resolve member; supports X-LLMHOST-MEMBER-ID
when using a shared team key.
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from llmhosts.rbac.models import AccessDecision, Role

if TYPE_CHECKING:
    from llmhosts.rbac.manager import TeamManager

logger = logging.getLogger(__name__)

MEMBER_ID_HEADER = "X-LLMHOST-MEMBER-ID"


class RBACMiddleware:
    """FastAPI middleware for RBAC enforcement.

    Checks:
    1. Is RBAC enabled? (team plan only - when TeamManager has a team)
    2. Who is the requester? (from API key or X-LLMHOST-MEMBER-ID header)
    3. What model are they requesting?
    4. Do they have access?

    When RBAC is disabled (no team), all requests pass through.
    """

    def __init__(self, team_manager: TeamManager) -> None:
        self._manager = team_manager

    async def check_request(self, api_key: str, model: str, member_id: str | None = None) -> AccessDecision:
        """Check if a request is allowed.

        Args:
            api_key: The API key from Authorization header (Bearer <key>).
            model: The model being requested.
            member_id: Optional member ID from X-LLMHOST-MEMBER-ID header (overrides api_key lookup).

        Returns:
            AccessDecision with allowed, reason, role, etc.
        """
        if not self._manager.has_team():
            # No team = RBAC disabled, allow all
            return AccessDecision(
                allowed=True,
                reason="RBAC disabled (no team)",
                role=Role.DEVELOPER,
                model_requested=model,
                budget_remaining=None,
            )

        member = None
        if member_id:
            members = await self._manager.list_members()
            member = next((m for m in members if m.id == member_id), None)
        if member is None and api_key:
            member = self._manager.get_member_by_api_key(api_key)

        if member is None:
            return AccessDecision(
                allowed=False,
                reason="Unknown requester: API key or member ID not recognized",
                role=Role.VIEWER,
                model_requested=model,
                budget_remaining=None,
            )

        return await self._manager.check_access(member.id, model)
