"""Action Session + permission preset policy (0.2.2.28 session-scoped execution)."""

from __future__ import annotations

from typing import Any

from .permission_profiles import PROFILE_UI_KEYS as PERMISSION_PRESETS
from .ui_capability_grants import UI_CAPABILITY_KEYS

PLAN_BOUND_MIN_TTL_SECONDS = 30 * 60

# Never auto-skip — destructive, publish, payment, install, root, system service.
ALWAYS_CONFIRM_COMMAND_TYPES = frozenset(
    {
        "social_post_publish",
        "browser_click_publish",
        "email_send",
        "mass_mail_send",
        "public_accusation_post",
        "message_send",
        "comment_submit",
        "payment_execute",
        "subscription_confirm",
        "folder_wipe",
        "db_drop",
        "package_remove",
        "empty_trash",
        "apply_update",
        "service_restart",
        "service_remove",
        "firewall_change",
        "install_unknown_software",
        "package_install_dry_run",
    }
)

HIGH_RISK_INPUT_COMMAND_TYPES = frozenset(
    {
        "mouse_move_relative",
        "keyboard_type_text",
        "capture_screenshot",
        "verify_screen_contains_text",
        "verify_web_draft",
        "verify_published",
        "open_web_composer",
    }
)

# In-scope for plan-bound web-post sessions after the single plan confirm.
WEB_PLAN_BOUND_AUTO_COMMAND_TYPES = frozenset(
    {
        "browser_open_url",
        "open_url",
        "keyboard_type_text",
        "insert_exact_text",
        "generate_content",
        "describe_active_window",
        "verify_web_draft",
        "verify_published",
        "open_web_composer",
        "capture_screenshot",
        "verify_screen_contains_text",
    }
)

INPUT_UI_CAPABILITIES = frozenset({"mouse_control", "keyboard_control", "screen_vision"})

# Outside plan-bound sessions: which risk tiers still require modal confirm per preset.
PRESET_CONFIRM_RISKS: dict[str, frozenset[str]] = {
    "minimal": frozenset({"medium", "high", "critical"}),
    "standard": frozenset({"high", "critical"}),
    "full": frozenset({"critical"}),
    "expert": frozenset({"critical"}),
}

PERMISSION_PRESET_ORDER: tuple[str, ...] = ("expert", "full", "standard", "minimal")


def infer_permission_preset(granted_ui_keys: set[str] | frozenset[str]) -> str:
    """Best-match permission preset from active UI capability grants."""
    granted = frozenset(str(k).strip() for k in granted_ui_keys if str(k).strip())
    for preset in PERMISSION_PRESET_ORDER:
        if PERMISSION_PRESETS.get(preset) == granted:
            return preset
    for preset in PERMISSION_PRESET_ORDER:
        required = PERMISSION_PRESETS.get(preset, frozenset())
        if required and required.issubset(granted):
            return preset
    return "minimal"


def command_always_requires_confirm(command_type: str, payload: dict[str, Any] | None = None) -> bool:
    ctype = str(command_type or "").strip().lower()
    if ctype in ALWAYS_CONFIRM_COMMAND_TYPES:
        return True
    payload = payload or {}
    execution_profile = str(payload.get("execution_profile") or "user").strip().lower()
    if execution_profile == "root":
        return True
    elevation_state = str(payload.get("elevation_state") or "").strip().lower()
    if elevation_state in {"requested", "approved"} and execution_profile == "root":
        return True
    return False


def plan_step_matches_session(
    session_scope: dict[str, Any],
    *,
    plan_id: str,
) -> bool:
    bound = str(session_scope.get("bound_to_plan_id") or "").strip()
    if not bound:
        return True
    step_plan = str(plan_id or "").strip()
    return bool(step_plan) and step_plan == bound


def permission_preset_allows_risk_skip(
    permission_preset: str,
    *,
    risk_level: str,
    command_type: str,
    plan_bound: bool,
) -> bool:
    preset = str(permission_preset or "minimal").strip().lower()
    risk = str(risk_level or "low").strip().lower()
    ctype = str(command_type or "").strip().lower()

    if risk == "critical":
        return False

    if plan_bound:
        if ctype in WEB_PLAN_BOUND_AUTO_COMMAND_TYPES:
            if risk == "critical":
                return False
            if risk == "high":
                if ctype in {"keyboard_type_text", "mouse_move_relative"}:
                    return preset in {"standard", "full", "expert"}
                return True
            return risk in {"low", "medium"}
        if risk == "high":
            if ctype in HIGH_RISK_INPUT_COMMAND_TYPES:
                return preset in {"full", "expert"}
            return False
        return risk in {"low", "medium"}

    confirm_risks = PRESET_CONFIRM_RISKS.get(preset, PRESET_CONFIRM_RISKS["minimal"])
    return risk not in confirm_risks


def session_confirmation_allows_skip(
    confirmation_mode: str,
    *,
    plan_bound: bool,
) -> bool:
    mode = str(confirmation_mode or "first_only").strip().lower()
    if mode == "every_command":
        return False
    if plan_bound and mode == "never_in_scope":
        return True
    if mode in {"never_in_scope", "first_only"}:
        return True
    return False


COMMAND_TYPE_UI_CAPABILITY: dict[str, str | None] = {
    "read_file_in_workspace": "file_access",
    "write_file_in_workspace": "file_access",
    "open_folder": "file_access",
    "open_document_edit": "application_control",
    "application_launch": "application_control",
    "empty_trash": "file_access",
    "social_post_draft": "application_control",
    "email_compose": "application_control",
    "email_send": "application_control",
    "mouse_move_relative": "mouse_control",
    "keyboard_type_text": "keyboard_control",
    "browser_open_url": "network_control",
    "open_url": "network_control",
    "web_fetch_bounded": "network_control",
    "summarize_content": "network_control",
    "generate_content": "network_control",
    "insert_exact_text": "network_control",
    "verify_workspace_file": "file_access",
    "network_diagnostics": "network_control",
    "capture_screenshot": "screen_vision",
    "verify_screen_contains_text": "screen_vision",
    "verify_web_draft": "screen_vision",
    "verify_published": "screen_vision",
    "describe_active_window": "screen_vision",
    "open_web_composer": "screen_vision",
    "package_install_dry_run": "software_management",
    "apply_update": "software_management",
    "service_restart": "software_management",
}


def ui_capability_for_command(command_type: str) -> str | None:
    return COMMAND_TYPE_UI_CAPABILITY.get(str(command_type or "").strip().lower())


def granted_ui_keys_from_enabled(enabled: dict[str, bool]) -> set[str]:
    return {key for key in UI_CAPABILITY_KEYS if enabled.get(key)}
