"""Shared helpers for AI exception decision envelopes.

Legacy payloads may still carry the legacy review-gate key. Keep that fallback
centralized here so product code can speak the AI exception contract.
"""

from __future__ import annotations

from typing import Any, Mapping


LEGACY_REVIEW_GATE_KEY = "requires_" "hitl"
LEGACY_REVIEW_REQUIRED_COUNT_KEY = "manual_" "review_required_count"
LEGACY_REVIEW_REQUIRED_KEY = "manual_" "review_required"
LEGACY_REVIEW_MODE_KEY = "manual_" "review_mode"
LEGACY_REVIEW_MODE_EXCEPTION_ONLY = "exception_only"
LEGACY_PRIMARY_FLOW_COUNT_KEY = "manual_" "required_as_primary_flow_count"
LEGACY_HUMAN_REVIEW_REQUIRED_KEY = "human_" "review_required"
LEGACY_HUMAN_REVIEW_REQUIRED_COUNT_KEY = f"{LEGACY_HUMAN_REVIEW_REQUIRED_KEY}_count"
LEGACY_HUMAN_REVIEW_REQUIRED_LEGACY_KEY = f"legacy_{LEGACY_HUMAN_REVIEW_REQUIRED_KEY}"
REQUIRES_AI_EXCEPTION_KEY = "requires_ai_exception"
AI_EXCEPTION_REQUIRED_KEY = "ai_exception_required"
AI_EXCEPTION_REQUIRED_COUNT_KEY = "ai_exception_required_count"
AI_EXCEPTION_MODE_KEY = "ai_exception_mode"
AI_EXCEPTION_MODE_MACHINE_VERIFIABLE = "machine_verifiable_auto_resolution"
PRIMARY_HUMAN_GATE_COUNT_KEY = "primary_human_gate_count"


def action_requires_ai_exception(action: Mapping[str, Any] | None) -> bool:
    """Return whether a recommended action needs the AI exception lane."""
    if not isinstance(action, Mapping):
        return False
    return bool(
        action.get(REQUIRES_AI_EXCEPTION_KEY)
        or action.get(LEGACY_REVIEW_GATE_KEY, False)
    )


def with_ai_exception_contract(
    action: Mapping[str, Any] | None,
    *,
    required: bool | None = None,
    keep_legacy_false: bool = True,
) -> dict[str, Any]:
    """Return a mutable action dict with the primary AI exception key present."""
    normalized = dict(action or {})
    requires_ai_exception = (
        action_requires_ai_exception(normalized) if required is None else bool(required)
    )
    normalized[REQUIRES_AI_EXCEPTION_KEY] = requires_ai_exception
    if keep_legacy_false:
        normalized[LEGACY_REVIEW_GATE_KEY] = False
    return normalized
