from __future__ import annotations

from typing import Any

from liverylab_core import official_external_workflow, project_capabilities, project_types


STATUS_SUPPORTED = "supported"
STATUS_BLOCKED = "blocked"
STATUS_UNKNOWN = "unknown"

FEATURE_MY_LIVERIES = "my_liveries"
FEATURE_PACKAGE_EXPORT = "package_export"
FEATURE_ACTIVATE_IN_GAME = "activate_in_game"
FEATURE_EDITABLE_PREVIEW_TOOLS = "editable_preview_tools"
FEATURE_UV_EXPORT = "uv_export"
FEATURE_LAYER_STUDIO = "layer_studio"
FEATURE_OFFICIAL_MATERIAL_JSON = "official_material_json"
FEATURE_TYRE_BRANDS = "tyre_brands"
FEATURE_DRIVER_PROFILES = "driver_profiles"
FEATURE_NUMBERPLATES = "numberplates"
FEATURE_MATERIAL_FINISH = "material_finish"
FEATURE_DEEP_GAME_PATCHING = "deep_game_patching"


ADVANCED_ONLY_REASON = "This feature is available only for Advanced LiveryLab projects until official external livery support is researched."
PREVIEW_ASSETS_REASON = "Prepare Preview Assets for this car before using 3D preview, UV export or Layer Studio authoring."
OFFICIAL_ACTIVATION_REASON = "Official Activate in Game deploys to Saved Games/ACE/ExternalLiveries and requires active content.kspkg."
OFFICIAL_DEACTIVATION_REASON = "Official Deactivate in Game moves the Saved Games/ACE/ExternalLiveries deployment into LiveryLab disabled storage."


def _capabilities(entry: dict[str, Any] | None) -> dict[str, Any]:
    data = entry if isinstance(entry, dict) else {}
    caps = data.get("capabilities")
    return caps if isinstance(caps, dict) else {}


def _cap_ready(capabilities: dict[str, Any], key: str) -> bool:
    return capabilities.get(key) is True


def _row(key: str, label: str, status: str, reason: str = "", required: list[str] | None = None) -> dict[str, Any]:
    return {
        "key": key,
        "label": label,
        "status": status,
        "supported": status == STATUS_SUPPORTED,
        "reason": reason,
        "requiredCapabilities": list(required or []),
    }


def feature_rows_for_entry(entry: dict[str, Any] | None) -> list[dict[str, Any]]:
    data = entry if isinstance(entry, dict) else {}
    project_type = project_types.project_type_for_entry(data)
    official = project_type == project_types.PROJECT_TYPE_OFFICIAL_EXTERNAL_LIVERY
    caps = _capabilities(data)
    preview_ready = _cap_ready(caps, project_capabilities.CAP_PREVIEW_ASSETS_READY)
    full_extract_ready = _cap_ready(caps, project_capabilities.CAP_FULL_EXTRACTED_CONTENT_READY)

    if official:
        preview_status = STATUS_SUPPORTED if preview_ready else STATUS_BLOCKED
        preview_reason = "" if preview_ready else PREVIEW_ASSETS_REASON
        return [
            _row(FEATURE_MY_LIVERIES, "My Liveries", STATUS_SUPPORTED),
            _row(FEATURE_PACKAGE_EXPORT, "Official package export", STATUS_SUPPORTED),
            _row(FEATURE_ACTIVATE_IN_GAME, "Official Activate in Game", STATUS_SUPPORTED),
            _row(FEATURE_EDITABLE_PREVIEW_TOOLS, "3D Preview", preview_status, preview_reason, [project_capabilities.CAP_PREVIEW_ASSETS_READY]),
            _row(FEATURE_UV_EXPORT, "UV mesh PNG export", preview_status, preview_reason, [project_capabilities.CAP_PREVIEW_ASSETS_READY]),
            _row(FEATURE_LAYER_STUDIO, "Layer Studio PNG authoring", preview_status, preview_reason, [project_capabilities.CAP_PREVIEW_ASSETS_READY]),
            _row(FEATURE_OFFICIAL_MATERIAL_JSON, "Official material JSON", STATUS_SUPPORTED),
            _row(FEATURE_TYRE_BRANDS, "Tyre Brands", STATUS_UNKNOWN, ADVANCED_ONLY_REASON),
            _row(FEATURE_DRIVER_PROFILES, "Driver Profiles", STATUS_UNKNOWN, ADVANCED_ONLY_REASON),
            _row(FEATURE_NUMBERPLATES, "Custom Rear Plates / Numberplates", STATUS_UNKNOWN, ADVANCED_ONLY_REASON),
            _row(FEATURE_MATERIAL_FINISH, "Paint finish", STATUS_SUPPORTED),
            _row(FEATURE_DEEP_GAME_PATCHING, "Deep game-file patching", STATUS_BLOCKED, ADVANCED_ONLY_REASON),
        ]

    advanced_status = STATUS_SUPPORTED if full_extract_ready else STATUS_BLOCKED
    advanced_reason = "" if full_extract_ready else "Full extracted content is required for advanced extracted-content tools."
    return [
        _row(FEATURE_MY_LIVERIES, "My Liveries", STATUS_SUPPORTED),
        _row(FEATURE_PACKAGE_EXPORT, "LiveryLab package export", STATUS_SUPPORTED),
        _row(FEATURE_ACTIVATE_IN_GAME, "Advanced Activate in Game", STATUS_SUPPORTED),
        _row(FEATURE_EDITABLE_PREVIEW_TOOLS, "3D Preview", advanced_status, advanced_reason, [project_capabilities.CAP_FULL_EXTRACTED_CONTENT_READY]),
        _row(FEATURE_UV_EXPORT, "UV mesh PNG export", advanced_status, advanced_reason, [project_capabilities.CAP_FULL_EXTRACTED_CONTENT_READY]),
        _row(FEATURE_LAYER_STUDIO, "Layer Studio", advanced_status, advanced_reason, [project_capabilities.CAP_FULL_EXTRACTED_CONTENT_READY]),
        _row(FEATURE_OFFICIAL_MATERIAL_JSON, "Official material JSON", STATUS_BLOCKED, "Official material JSON applies only to official external liveries."),
        _row(FEATURE_TYRE_BRANDS, "Tyre Brands", STATUS_SUPPORTED),
        _row(FEATURE_DRIVER_PROFILES, "Driver Profiles", STATUS_SUPPORTED),
        _row(FEATURE_NUMBERPLATES, "Custom Rear Plates / Numberplates", STATUS_SUPPORTED),
        _row(FEATURE_MATERIAL_FINISH, "Advanced material finish", STATUS_SUPPORTED),
        _row(FEATURE_DEEP_GAME_PATCHING, "Deep game-file patching", STATUS_SUPPORTED),
    ]


def _feature_status(rows: list[dict[str, Any]], feature_key: str) -> str:
    for row in rows:
        if row.get("key") == feature_key:
            return str(row.get("status") or STATUS_UNKNOWN)
    return STATUS_UNKNOWN


def _feature_supported(rows: list[dict[str, Any]], feature_key: str) -> bool:
    return _feature_status(rows, feature_key) == STATUS_SUPPORTED


def _feature_reason(rows: list[dict[str, Any]], feature_key: str) -> str:
    for row in rows:
        if row.get("key") == feature_key:
            return str(row.get("reason") or "")
    return ""


def permission_matrix(
    entry: dict[str, Any] | None,
    *,
    editable: bool,
    read_only: bool,
    official_external: bool,
    official_external_role: str = "",
) -> dict[str, Any]:
    rows = feature_rows_for_entry(entry)
    official_project = official_external and official_external_role == official_external_workflow.ROLE_PROJECT
    official_deployable = official_external and official_external_role in {
        official_external_workflow.ROLE_PROJECT,
        official_external_workflow.ROLE_LIBRARY,
    }
    if official_external:
        permissions = {
            "canEditMetadata": editable,
            "canEditProjectMetadata": editable,
            "canEditPreviewImage": editable or read_only,
            "canEditTyres": False,
            "canEditDriver": False,
            "canEditNumberplate": False,
            "canEditMaterialFinish": editable,
            "canExportPackage": editable,
            "canUseEditablePreviewTools": editable and _feature_supported(rows, FEATURE_EDITABLE_PREVIEW_TOOLS),
            "canUseReadOnlyPreview": True,
            "canActivateInGame": official_deployable,
            "canDeactivateInGame": True,
            "canRemove": True,
            "canTrash": official_project,
            "canBackupTransfer": True,
            "canDuplicateProject": official_project and editable,
            "canCreateEditableProject": False,
        }
        reasons = {
            "canEditTyres": _feature_reason(rows, FEATURE_TYRE_BRANDS),
            "canEditDriver": _feature_reason(rows, FEATURE_DRIVER_PROFILES),
            "canEditNumberplate": _feature_reason(rows, FEATURE_NUMBERPLATES),
            "canEditMaterialFinish": _feature_reason(rows, FEATURE_MATERIAL_FINISH),
            "canUseEditablePreviewTools": _feature_reason(rows, FEATURE_EDITABLE_PREVIEW_TOOLS),
            "canActivateInGame": "" if official_deployable else "This Official external livery cannot be activated from its current storage role.",
            "canDeactivateInGame": "",
            "canCreateEditableProject": "Read-only Official liveries cannot be converted into editable projects.",
        }
    else:
        permissions = {
            "canEditMetadata": editable,
            "canEditProjectMetadata": editable,
            "canEditPreviewImage": editable or read_only,
            "canEditTyres": editable,
            "canEditDriver": editable,
            "canEditNumberplate": editable,
            "canEditMaterialFinish": editable,
            "canExportPackage": editable,
            "canUseEditablePreviewTools": editable,
            "canUseReadOnlyPreview": True,
            "canActivateInGame": True,
            "canDeactivateInGame": True,
            "canRemove": True,
            "canTrash": True,
            "canBackupTransfer": True,
            "canDuplicateProject": editable,
            "canCreateEditableProject": read_only,
        }
        reasons = {}

    return {
        "permissions": permissions,
        "permissionReasons": {key: value for key, value in reasons.items() if value},
        "featureRows": rows,
    }
