from django.contrib import messages
from django.shortcuts import redirect

MODULES = [
    ('applications',  'Applications'),
    ('students',      'Students'),
    ('payments',      'Payments'),
    ('courses',       'Courses'),
    ('programs',      'Programs'),
    ('staff',         'Staff'),
    ('timetable',     'Timetable'),
    ('certificates',  'Certificates'),
    ('gallery',       'Gallery'),
    ('testimonials',  'Testimonials'),
    ('notifications', 'Notifications'),
    ('donations',     'Donations'),
    ('reports',       'Reports'),
    ('direct_enroll', 'Direct Enroll'),
]

MODULE_KEYS = [m[0] for m in MODULES]


def _get_module_perms(user):
    """
    Return cached list of AdminModulePermission for an ADMIN user.

    Results are stored on the user object for the lifetime of the request
    (same pattern as Django's own _perm_cache), so both ModulePermissionMixin
    and the context processor share one DB query per request.
    """
    if not hasattr(user, '_module_perms_cache'):
        from portal.models import AdminModulePermission
        user._module_perms_cache = list(AdminModulePermission.objects.filter(user=user))
    return user._module_perms_cache


def user_can(user, module, action='view'):
    """
    Return True if user may perform action ('view'|'edit'|'delete') on module.

    SUPER_ADMIN always returns True.
    ADMIN with no permissions configured returns True (backward-compatible default).
    ADMIN with permissions configured returns the specific flag.
    """
    from django.contrib.auth import get_user_model
    User = get_user_model()

    if not getattr(user, 'is_authenticated', False):
        return False
    if user.role == User.SUPER_ADMIN:
        return True
    if user.role != User.ADMIN:
        return False

    all_perms = _get_module_perms(user)
    if not all_perms:
        return True  # No restrictions configured → full access (backward compat)

    perm = next((p for p in all_perms if p.module == module), None)
    if perm is None:
        return False
    return getattr(perm, f'can_{action}', False)


class ModulePermissionMixin:
    """
    Mixin for admin views to gate by module permission.

    Usage on a view class:
        module = 'courses'                 # required
        module_action = 'edit'             # optional; None → auto-detect (GET/HEAD=view, POST=edit)
        module_action = 'delete'           # set this on delete/confirm-delete views
    """
    module = None
    module_action = None

    def dispatch(self, request, *args, **kwargs):
        if self.module:
            action = self.module_action
            if action is None:
                action = 'view' if request.method in ('GET', 'HEAD') else 'edit'
            if not user_can(request.user, self.module, action):
                messages.error(request, 'You do not have permission to access this section.')
                return redirect('portal:admin_dashboard')
        return super().dispatch(request, *args, **kwargs)
