# app/core/permissions.py
"""
Permission constants and checking logic for RBAC.

This module defines:
- Vendor-specific permissions
- Permission groups (for easier role creation)
- Permission checking utilities
"""

from enum import Enum


class VendorPermissions(str, Enum):
    """
    All available permissions within a vendor context.

    Naming convention: RESOURCE_ACTION
    """

    # Dashboard
    DASHBOARD_VIEW = "dashboard.view"

    # Products
    PRODUCTS_VIEW = "products.view"
    PRODUCTS_CREATE = "products.create"
    PRODUCTS_EDIT = "products.edit"
    PRODUCTS_DELETE = "products.delete"
    PRODUCTS_IMPORT = "products.import"
    PRODUCTS_EXPORT = "products.export"

    # Stock/Inventory
    STOCK_VIEW = "stock.view"
    STOCK_EDIT = "stock.edit"
    STOCK_TRANSFER = "stock.transfer"

    # Orders
    ORDERS_VIEW = "orders.view"
    ORDERS_EDIT = "orders.edit"
    ORDERS_CANCEL = "orders.cancel"
    ORDERS_REFUND = "orders.refund"

    # Customers
    CUSTOMERS_VIEW = "customers.view"
    CUSTOMERS_EDIT = "customers.edit"
    CUSTOMERS_DELETE = "customers.delete"
    CUSTOMERS_EXPORT = "customers.export"

    # Marketing
    MARKETING_VIEW = "marketing.view"
    MARKETING_CREATE = "marketing.create"
    MARKETING_SEND = "marketing.send"

    # Reports
    REPORTS_VIEW = "reports.view"
    REPORTS_FINANCIAL = "reports.financial"
    REPORTS_EXPORT = "reports.export"

    # Settings
    SETTINGS_VIEW = "settings.view"
    SETTINGS_EDIT = "settings.edit"
    SETTINGS_THEME = "settings.theme"
    SETTINGS_DOMAINS = "settings.domains"

    # Team Management
    TEAM_VIEW = "team.view"
    TEAM_INVITE = "team.invite"
    TEAM_EDIT = "team.edit"
    TEAM_REMOVE = "team.remove"

    # Marketplace Imports
    IMPORTS_VIEW = "imports.view"
    IMPORTS_CREATE = "imports.create"
    IMPORTS_CANCEL = "imports.cancel"


class PermissionGroups:
    """Pre-defined permission groups for common roles."""

    # Full access (for owners)
    OWNER: set[str] = set(p.value for p in VendorPermissions)

    # Manager - Can do most things except team management and critical settings
    MANAGER: set[str] = {
        VendorPermissions.DASHBOARD_VIEW.value,
        VendorPermissions.PRODUCTS_VIEW.value,
        VendorPermissions.PRODUCTS_CREATE.value,
        VendorPermissions.PRODUCTS_EDIT.value,
        VendorPermissions.PRODUCTS_DELETE.value,
        VendorPermissions.PRODUCTS_IMPORT.value,
        VendorPermissions.PRODUCTS_EXPORT.value,
        VendorPermissions.STOCK_VIEW.value,
        VendorPermissions.STOCK_EDIT.value,
        VendorPermissions.STOCK_TRANSFER.value,
        VendorPermissions.ORDERS_VIEW.value,
        VendorPermissions.ORDERS_EDIT.value,
        VendorPermissions.ORDERS_CANCEL.value,
        VendorPermissions.ORDERS_REFUND.value,
        VendorPermissions.CUSTOMERS_VIEW.value,
        VendorPermissions.CUSTOMERS_EDIT.value,
        VendorPermissions.CUSTOMERS_EXPORT.value,
        VendorPermissions.MARKETING_VIEW.value,
        VendorPermissions.MARKETING_CREATE.value,
        VendorPermissions.MARKETING_SEND.value,
        VendorPermissions.REPORTS_VIEW.value,
        VendorPermissions.REPORTS_FINANCIAL.value,
        VendorPermissions.REPORTS_EXPORT.value,
        VendorPermissions.SETTINGS_VIEW.value,
        VendorPermissions.SETTINGS_THEME.value,
        VendorPermissions.IMPORTS_VIEW.value,
        VendorPermissions.IMPORTS_CREATE.value,
        VendorPermissions.IMPORTS_CANCEL.value,
    }

    # Staff - Can view and edit products/orders but limited access
    STAFF: set[str] = {
        VendorPermissions.DASHBOARD_VIEW.value,
        VendorPermissions.PRODUCTS_VIEW.value,
        VendorPermissions.PRODUCTS_CREATE.value,
        VendorPermissions.PRODUCTS_EDIT.value,
        VendorPermissions.STOCK_VIEW.value,
        VendorPermissions.STOCK_EDIT.value,
        VendorPermissions.ORDERS_VIEW.value,
        VendorPermissions.ORDERS_EDIT.value,
        VendorPermissions.CUSTOMERS_VIEW.value,
        VendorPermissions.CUSTOMERS_EDIT.value,
    }

    # Support - Can view and assist with orders/customers
    SUPPORT: set[str] = {
        VendorPermissions.DASHBOARD_VIEW.value,
        VendorPermissions.PRODUCTS_VIEW.value,
        VendorPermissions.ORDERS_VIEW.value,
        VendorPermissions.ORDERS_EDIT.value,
        VendorPermissions.CUSTOMERS_VIEW.value,
        VendorPermissions.CUSTOMERS_EDIT.value,
    }

    # Viewer - Read-only access
    VIEWER: set[str] = {
        VendorPermissions.DASHBOARD_VIEW.value,
        VendorPermissions.PRODUCTS_VIEW.value,
        VendorPermissions.STOCK_VIEW.value,
        VendorPermissions.ORDERS_VIEW.value,
        VendorPermissions.CUSTOMERS_VIEW.value,
        VendorPermissions.REPORTS_VIEW.value,
    }

    # Marketing - Focused on marketing and customer communication
    MARKETING: set[str] = {
        VendorPermissions.DASHBOARD_VIEW.value,
        VendorPermissions.CUSTOMERS_VIEW.value,
        VendorPermissions.CUSTOMERS_EXPORT.value,
        VendorPermissions.MARKETING_VIEW.value,
        VendorPermissions.MARKETING_CREATE.value,
        VendorPermissions.MARKETING_SEND.value,
        VendorPermissions.REPORTS_VIEW.value,
    }


class PermissionChecker:
    """Utility class for permission checking."""

    @staticmethod
    def has_permission(permissions: list[str], required_permission: str) -> bool:
        """Check if a permission list contains a required permission."""
        return required_permission in permissions

    @staticmethod
    def has_any_permission(
        permissions: list[str], required_permissions: list[str]
    ) -> bool:
        """Check if a permission list contains ANY of the required permissions."""
        return any(perm in permissions for perm in required_permissions)

    @staticmethod
    def has_all_permissions(
        permissions: list[str], required_permissions: list[str]
    ) -> bool:
        """Check if a permission list contains ALL of the required permissions."""
        return all(perm in permissions for perm in required_permissions)

    @staticmethod
    def get_missing_permissions(
        permissions: list[str], required_permissions: list[str]
    ) -> list[str]:
        """Get list of missing permissions."""
        return [perm for perm in required_permissions if perm not in permissions]


# Helper function to get permissions for a role preset
def get_preset_permissions(preset_name: str) -> set[str]:
    """
    Get permissions for a preset role.

    Args:
        preset_name: Name of the preset (manager, staff, support, viewer, marketing)

    Returns:
        Set of permission strings
    """
    presets = {
        "owner": PermissionGroups.OWNER,
        "manager": PermissionGroups.MANAGER,
        "staff": PermissionGroups.STAFF,
        "support": PermissionGroups.SUPPORT,
        "viewer": PermissionGroups.VIEWER,
        "marketing": PermissionGroups.MARKETING,
    }
    return presets.get(preset_name.lower(), set())
