"""External-entry auth helpers for MCP adapter."""
from __future__ import annotations

import os

from security.auth.api_keys import ResolvedAPIKey
from security.auth.core import AuthInput, authorize, resolve_agent_api_key


def effective_caller_api_key(provided_api_key: str | None) -> str:
    """Resolve effective caller key with tool-arg precedence."""
    return (provided_api_key or "").strip() or os.getenv(
        "AIF_MCP_CALLER_API_KEY", ""
    ).strip()


async def authenticate_mcp_caller(provided_api_key: str | None) -> ResolvedAPIKey:
    """
    Authenticate MCP caller using per-agent keys only.

    Order:
    1) Tool arg `caller_api_key`
    2) Env fallback `AIF_MCP_CALLER_API_KEY`
    3) Resolve via Normbase `/api/v1/keys/resolve`
    """
    # Precedence keeps explicit tool params in control while supporting
    # client environments that cannot inject tool arguments automatically.
    effective_api_key = effective_caller_api_key(provided_api_key)
    if not effective_api_key:
        raise PermissionError("Unauthorized: missing MCP caller API key.")

    result = await authorize(
        AuthInput(
            entry_type="mcp",
            api_key=effective_api_key,
            action="tool:authenticate_mcp_caller",
            required_scopes=[],
        ),
        resolver=resolve_agent_api_key,
    )
    if result.decision != "allow":
        raise PermissionError("Unauthorized: invalid MCP API key.")
    return ResolvedAPIKey(
        key_id=result.key_id,
        agent_id=result.agent_id,
        scopes=result.scopes,
        is_active=True,
        expires_at=None,
    )


async def authorize_mcp_tool_call(
    provided_api_key: str | None,
    *,
    tool_name: str,
    required_scopes: list[str] | None = None,
    resource_agent_id: str | None = None,
) -> ResolvedAPIKey:
    """Authorize one MCP tool call and return normalized key principal."""
    effective_api_key = effective_caller_api_key(provided_api_key)
    result = await authorize(
        AuthInput(
            entry_type="mcp",
            api_key=effective_api_key,
            action=f"tool:{(tool_name or '').strip()}",
            required_scopes=list(required_scopes or []),
            resource_agent_id=resource_agent_id,
        ),
        resolver=resolve_agent_api_key,
    )
    if result.decision == "allow":
        return ResolvedAPIKey(
            key_id=result.key_id,
            agent_id=result.agent_id,
            scopes=result.scopes,
            is_active=True,
            expires_at=None,
        )
    if result.reason == "missing_api_key":
        raise PermissionError("Unauthorized: missing MCP caller API key.")
    if result.reason.startswith("missing_scope:"):
        scope = result.reason.split(":", 1)[1]
        raise PermissionError(f"Forbidden: missing required scope '{scope}'.")
    if result.reason == "agent_mismatch":
        raise PermissionError("Unauthorized: key does not match target agent.")
    raise PermissionError("Unauthorized: invalid MCP API key.")

