# core/permissions.py
from django.contrib.auth import get_user_model
from django.http import HttpResponseForbidden
from functools import wraps

from users.models import Menu, UserPermissions

MENU_ACTIONS = ('view', 'add', 'edit', 'delete', 'export')


def build_session_permissions(user):
    """
    Called on login (or whenever you want to refresh).
    Creates two session objects:
      - request.session['assigned_menu']  -> list of allowed menu_action codes
      - request.session['menu_permissions'] -> dict keyed by menu_action with action booleans
    """
    perms_qs = (
        UserPermissions.objects
        .select_related('ref_menu')
        .filter(ref_user=user, ref_menu__menu_status=True)
    )

    assigned_menu = []
    menu_permissions = {}

    for up in perms_qs:
        code = (up.ref_menu.menu_action or '').upper().strip()
        if not code:
            # Menus with no code are sections/headers; skip adding permissions
            continue

        # store booleans for this code
        menu_permissions[code] = {
            'can_view':   bool(up.can_view),
            'can_add':    bool(up.can_add),
            'can_edit':   bool(up.can_edit),
            'can_delete': bool(up.can_delete),
            'can_export': bool(up.can_export),
        }
        if up.can_view:
            assigned_menu.append(code)

    # Optional: superusers see everything
    if user.is_superuser:
        # include all active menu codes
        for m in Menu.objects.filter(menu_status=True):
            code = (m.menu_action or '').upper().strip()
            if code:
                assigned_menu.append(code)
                if code not in menu_permissions:
                    menu_permissions[code] = {
                        'can_view': True, 'can_add': True, 'can_edit': True, 'can_delete': True, 'can_export': True
                    }

    # de-dup & save
    assigned_menu = sorted(list(set(assigned_menu)))
    return assigned_menu, menu_permissions


def get_module_perms(request, menu_code):
    """
    Return dict with can_* flags for a given menu code (like 'USER').
    Matches your old behavior (only can_view, can_add, etc.).
    """
    perms = {
        'can_view': 0,
        'can_add': 0,
        'can_edit': 0,
        'can_delete': 0,
        'can_export': 0,
    }

    if not request.user.is_authenticated:
        return perms

    menu_code = (menu_code or '').upper().strip()
    menu_permissions = request.session.get('menu_permissions', {})

    # Superuser = full access
    if request.user.is_superuser:
        return {k: 1 for k in perms}

    if menu_code in menu_permissions:
        perms.update({
            'can_view':   1 if menu_permissions[menu_code].get('can_view') else 0,
            'can_add':    1 if menu_permissions[menu_code].get('can_add') else 0,
            'can_edit':   1 if menu_permissions[menu_code].get('can_edit') else 0,
            'can_delete': 1 if menu_permissions[menu_code].get('can_delete') else 0,
            'can_export': 1 if menu_permissions[menu_code].get('can_export') else 0,
        })

    return perms


# def get_module_perms(request, menu_code):
#     """
#     Return dict with can_* flags for a given menu code (like 'USER').
#     """
#     if not request.user.is_authenticated:
#         return {'is_default': 0, 'can_view': 0, 'can_add': 0, 'can_edit': 0, 'can_delete': 0, 'can_export': 0}

#     menu_code = (menu_code or '').upper().strip()
#     menu_permissions = request.session.get('menu_permissions', {})

#     # Treat superuser as full-access fallback
#     if request.user.is_superuser:
#         return {'is_default': 1, 'can_view': 1, 'can_add': 1, 'can_edit': 1, 'can_delete': 1, 'can_export': 1}

#     perms = menu_permissions.get(menu_code, {})
#     return {
#         'is_default': 1 if request.user.is_superuser else 0,  # or keep 0 if you want
#         'can_view':   1 if perms.get('can_view') else 0,
#         'can_add':    1 if perms.get('can_add') else 0,
#         'can_edit':   1 if perms.get('can_edit') else 0,
#         'can_delete': 1 if perms.get('can_delete') else 0,
#         'can_export': 1 if perms.get('can_export') else 0,
#     }


def require_menu_perm(menu_code, action='view'):
    """
    Decorator for view-level guard (like your CI checks):
      @require_menu_perm('USER', 'view')
      @require_menu_perm('USER', 'add')
    """
    assert action in MENU_ACTIONS

    def decorator(view_func):
        @wraps(view_func)
        def _wrapped(request, *args, **kwargs):
            perms = get_module_perms(request, menu_code)
            if not perms.get(f'can_{action}', 0):
                return HttpResponseForbidden("Unauthorized Access")
            return view_func(request, *args, **kwargs)
        return _wrapped
    return decorator
