"""Immutable permission profiles — capability bundles mapped to UI grant keys."""

from __future__ import annotations

from typing import FrozenSet

_PROFILE_UI_KEY_NAMES: tuple[str, ...] = (
    "file_access",
    "application_control",
    "mouse_control",
    "keyboard_control",
    "network_control",
    "software_management",
    "root_operations",
    "screen_vision",
)

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

# Human-readable capability bundle ids (i18n: profile.bundle.<id>).
PROFILE_CAPABILITY_BUNDLES: dict[str, tuple[str, ...]] = {
    "minimal": (
        "file_workspace",
        "diagnostics",
        "network_readonly",
        "logs",
    ),
    "standard": (
        "file_workspace",
        "diagnostics",
        "network_readonly",
        "logs",
        "app_launch",
        "browser_automation",
        "sites_apps",
        "clipboard",
        "file_write_limited",
    ),
    "full": (
        "file_workspace",
        "diagnostics",
        "network_readonly",
        "logs",
        "app_launch",
        "browser_automation",
        "sites_apps",
        "clipboard",
        "file_write_limited",
        "keyboard_automation",
        "mouse_automation",
        "screen_vision",
        "development",
        "software_management",
        "documents",
        "automation",
    ),
    "expert": (
        "file_workspace",
        "diagnostics",
        "network_readonly",
        "logs",
        "app_launch",
        "browser_automation",
        "sites_apps",
        "clipboard",
        "file_write_limited",
        "keyboard_automation",
        "mouse_automation",
        "screen_vision",
        "development",
        "software_management",
        "documents",
        "automation",
        "root_operations",
        "shell",
        "package_management",
        "system_configuration",
        "service_management",
        "device_management",
    ),
}

# Profile → UI capability grant keys (immutable bundles; execution layer unchanged).
PROFILE_UI_KEYS: dict[str, FrozenSet[str]] = {
    "minimal": frozenset({"file_access", "network_control"}),
    "standard": frozenset({"file_access", "network_control", "application_control"}),
    "full": frozenset(
        {
            "file_access",
            "network_control",
            "application_control",
            "mouse_control",
            "keyboard_control",
            "screen_vision",
            "software_management",
        }
    ),
    "expert": frozenset(_PROFILE_UI_KEY_NAMES),
}

# Backward-compatible alias used by action_session_policy and Security tab presets.
PERMISSION_PRESETS: dict[str, FrozenSet[str]] = PROFILE_UI_KEYS

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

PROFILE_RISK_LEVEL: dict[str, str] = {
    "minimal": "low",
    "standard": "medium",
    "full": "high",
    "expert": "critical",
}

# Session lifetime keys (replace legacy 30m / 2h / 6h owner-grant UI).
SESSION_LIFETIME_KEYS: tuple[str, ...] = (
    "permanent",
    "app_exit",
    "device_shutdown",
    "single_task",
)

# Maps profile lifetime → CapabilityStateManager expiry_preset.
LIFETIME_TO_EXPIRY_PRESET: dict[str, str] = {
    "permanent": "permanent",
    "app_exit": "app_exit",
    "device_shutdown": "reboot",
    "single_task": "one_shot",
}

# Temporary action-session scope groups — auto-included by profile/task; not manual Security UI.
TEMPORARY_SCOPE_GROUPS: tuple[str, ...] = (
    "files_documents",
    "sites_apps",
    "input_automation",
    "development",
    "screen_vision",
    "software_management",
)

TEMPORARY_SCOPE_TO_SESSION_PRESETS: dict[str, tuple[str, ...]] = {
    "files_documents": ("files",),
    "sites_apps": ("web", "apps"),
    "input_automation": ("desktop",),
    "development": ("coding",),
    "screen_vision": ("desktop",),
    "software_management": ("maintenance",),
}


def profile_ui_keys(profile_key: str) -> frozenset[str]:
    return PROFILE_UI_KEYS.get(str(profile_key or "").strip().lower(), frozenset())


def profile_capability_bundles(profile_key: str) -> tuple[str, ...]:
    return PROFILE_CAPABILITY_BUNDLES.get(str(profile_key or "").strip().lower(), ())


def profile_risk_level(profile_key: str) -> str:
    return PROFILE_RISK_LEVEL.get(str(profile_key or "").strip().lower(), "medium")


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


def allowed_session_lifetimes(
    *,
    trust_state: str = "",
    paired: bool = False,
    authenticated: bool = False,
) -> frozenset[str]:
    """Trusted + authenticated pairing unlocks permanent lifetime."""
    trusted = str(trust_state or "").strip().lower() == "trusted"
    if trusted and paired and authenticated:
        return frozenset({"permanent", "app_exit", "device_shutdown"})
    return frozenset({"app_exit", "single_task"})


def resolve_lifetime_for_device(
    requested_lifetime: str,
    *,
    trust_state: str = "",
    paired: bool = False,
    authenticated: bool = False,
) -> str:
    """Clamp lifetime to device trust policy."""
    lifetime = str(requested_lifetime or "app_exit").strip().lower()
    allowed = allowed_session_lifetimes(
        trust_state=trust_state,
        paired=paired,
        authenticated=authenticated,
    )
    if lifetime in allowed:
        return lifetime
    if "app_exit" in allowed:
        return "app_exit"
    return "single_task"


def lifetime_to_expiry_preset(lifetime: str) -> str:
    return LIFETIME_TO_EXPIRY_PRESET.get(str(lifetime or "").strip().lower(), "app_exit")


def legacy_grants_to_profile(granted_ui_keys: set[str] | frozenset[str]) -> str:
    """Translate legacy per-checkbox grants into nearest profile key."""
    return infer_profile_from_ui_keys(granted_ui_keys)


def temporary_scopes_for_profile(profile_key: str) -> frozenset[str]:
    """Action-session preset keys auto-included for a profile (not manual UI)."""
    preset = str(profile_key or "").strip().lower()
    scopes: set[str] = set()
    if preset in {"standard", "full", "expert"}:
        scopes.update(TEMPORARY_SCOPE_TO_SESSION_PRESETS.get("files_documents", ()))
        scopes.update(TEMPORARY_SCOPE_TO_SESSION_PRESETS.get("sites_apps", ()))
    if preset in {"full", "expert"}:
        scopes.update(TEMPORARY_SCOPE_TO_SESSION_PRESETS.get("input_automation", ()))
        scopes.update(TEMPORARY_SCOPE_TO_SESSION_PRESETS.get("development", ()))
        scopes.update(TEMPORARY_SCOPE_TO_SESSION_PRESETS.get("screen_vision", ()))
        scopes.update(TEMPORARY_SCOPE_TO_SESSION_PRESETS.get("software_management", ()))
    return frozenset(scopes)
