# -*- coding: utf-8 -*-
"""
Django Permission System for Accounts App

This module provides a comprehensive permission system for the accounts app
with decorators, mixins, and utility functions for checking user permissions.
"""

from functools import wraps
from django.contrib import messages
from django.urls import reverse_lazy
from django.http import JsonResponse
from django.shortcuts import redirect
from django.core.exceptions import PermissionDenied
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin


class PermissionRequiredMixin(LoginRequiredMixin):
    """
    Mixin that checks if user has required permissions.
    Can be used with class-based views.
    """
    permission_required = None
    permission_denied_message = "You don't have permission to access this page."
    
    def dispatch(self, request, *args, **kwargs):
        if not self.has_permission():
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    "success": False,
                    "message": self.permission_denied_message
                }, status=403)
            else:
                messages.error(request, self.permission_denied_message)
                return redirect("core:dashboard")
        return super().dispatch(request, *args, **kwargs)
    
    def has_permission(self):
        """Check if user has required permissions."""
        if not self.permission_required:
            return True
        
        if isinstance(self.permission_required, str):
            permissions = [self.permission_required]
        else:
            permissions = self.permission_required
        
        return self.request.user.has_perms(permissions)


def permission_required(permission_codename, login_url=None, raise_exception=False):
    """
    Decorator for views that checks whether a user has permission to access the view.
    
    Args:
        permission_codename: String or list of permission codenames to check
        login_url: URL to redirect to if user is not authenticated
        raise_exception: Whether to raise PermissionDenied exception
    """
    def decorator(view_func):
        @wraps(view_func)
        @login_required(login_url=login_url)
        def _wrapped_view(request, *args, **kwargs):
            if isinstance(permission_codename, str):
                permissions = [permission_codename]
            else:
                permissions = permission_codename
            
            if not request.user.has_perms(permissions):
                if raise_exception:
                    raise PermissionDenied
                
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        "success": False,
                        "message": "You don't have permission to perform this action."
                    }, status=403)
                else:
                    messages.error(request, "You don't have permission to perform this action.")
                    return redirect("core:dashboard")
            
            return view_func(request, *args, **kwargs)
        return _wrapped_view
    return decorator


def ajax_permission_required(permission_codename):
    """
    Decorator specifically for AJAX views that checks permissions.
    """
    def decorator(view_func):
        @wraps(view_func)
        @login_required
        def _wrapped_view(request, *args, **kwargs):
            if isinstance(permission_codename, str):
                permissions = [permission_codename]
            else:
                permissions = permission_codename
            
            if not request.user.has_perms(permissions):
                return JsonResponse({
                    "success": False,
                    "message": "You don't have permission to perform this action."
                }, status=403)
            
            return view_func(request, *args, **kwargs)
        return _wrapped_view
    return decorator


def user_has_permission(user, permission_codename):
    """
    Utility function to check if a user has specific permission.
    
    Args:
        user: User instance
        permission_codename: String or list of permission codenames
    
    Returns:
        Boolean indicating if user has permission
    """
    if isinstance(permission_codename, str):
        permissions = [permission_codename]
    else:
        permissions = permission_codename
    
    return user.has_perms(permissions)


def get_user_permissions(user):
    """
    Get all permissions for a user including role-based permissions.
    
    Args:
        user: User instance
    
    Returns:
        QuerySet of permissions
    """
    from django.contrib.auth.models import Permission
    from apps.accounts.models import UserRole
    
    # Get direct user permissions
    user_permissions = user.user_permissions.all()
    
    # Get permissions from roles
    role_permissions = Permission.objects.filter(
        role__userrole__user=user,
        role__userrole__is_active=True
    ).distinct()
    
    # Combine permissions
    all_permissions = user_permissions.union(role_permissions)
    
    return all_permissions


class UserManagementPermissions:
    """Permission constants for user management."""
    
    # User permissions
    CAN_VIEW_USERS = "accounts.view_user"
    CAN_ADD_USERS = "accounts.add_user"
    CAN_CHANGE_USERS = "accounts.change_user"
    CAN_DELETE_USERS = "accounts.delete_user"
    
    # Role permissions
    CAN_VIEW_ROLES = "accounts.view_role"
    CAN_ADD_ROLES = "accounts.add_role"
    CAN_CHANGE_ROLES = "accounts.change_role"
    CAN_DELETE_ROLES = "accounts.delete_role" 
    
    # Permission permissions
    CAN_VIEW_PERMISSIONS = "auth.view_permission"
    CAN_ADD_PERMISSIONS = "auth.add_permission"
    CAN_CHANGE_PERMISSIONS = "auth.change_permission"
    CAN_DELETE_PERMISSIONS = "auth.delete_permission"
    
    # User role assignment permissions
    CAN_ASSIGN_ROLES = "accounts.add_userrole"
    CAN_REVOKE_ROLES = "accounts.delete_userrole"
    
    # Profile permissions
    CAN_VIEW_PROFILES = "accounts.view_profile"
    CAN_CHANGE_PROFILES = "accounts.change_profile"
    
    # Activity permissions
    CAN_VIEW_ACTIVITIES = "activities.view_activity"
    
    # Session permissions
    CAN_VIEW_SESSIONS = "accounts.view_usersession"
    CAN_TERMINATE_SESSIONS = "accounts.delete_usersession"


def create_default_permissions():
    """
    Create default permissions for the accounts app.
    This should be called during app initialization.
    """
    from django.contrib.auth.models import Permission
    from django.contrib.contenttypes.models import ContentType
    from apps.accounts.models import User, Role , UserRole, Profile, UserSession
    
    # Custom permissions that don't exist by default
    custom_permissions = [
        # User management
        ("can_manage_users", "Can manage all users"),
        ("can_view_user_details", "Can view user details"),
        ("can_export_users", "Can export user data"),
        
        # Role management
        ("can_assign_roles", "Can assign roles to users"),
        ("can_manage_permissions", "Can manage permissions"),
         
        
        # Profile management
        ("can_view_all_profiles", "Can view all user profiles"),
        ("can_manage_profiles", "Can manage user profiles"),
        
        # Session management
        ("can_view_all_sessions", "Can view all user sessions"),
        ("can_terminate_sessions", "Can terminate user sessions"),
        
        # Activity management
        ("can_view_all_activities", "Can view all user activities"),
    ]
    
    # Create custom permissions
    for codename, name in custom_permissions:
        content_type = ContentType.objects.get_for_model(User)
        permission, created = Permission.objects.get_or_create(
            codename=codename,
            name=name,
            content_type=content_type
        )
        if created:
            print(f"Created permission: {codename}")


def setup_default_roles():
    """
    Set up default roles with appropriate permissions.
    """
    from django.contrib.auth.models import Permission
    from apps.accounts.models import Role
    
    # Define default roles and their permissions
    default_roles = {
        "super_admin": {
            "name": "Super Administrator",
            "description": "Has full access to all system features",
            "permissions": [
                "accounts.add_user", "accounts.change_user", "accounts.delete_user", "accounts.view_user",
                "accounts.add_role", "accounts.change_role", "accounts.delete_role", "accounts.view_role", 
                "accounts.add_userrole", "accounts.delete_userrole", "accounts.view_userrole",
                "accounts.add_profile", "accounts.change_profile", "accounts.view_profile",
                "accounts.add_usersession", "accounts.change_usersession", "accounts.delete_usersession", "accounts.view_usersession",
                "accounts.can_manage_users", "accounts.can_assign_roles", "accounts.can_manage_permissions",
                "accounts.can_view_all_profiles", "accounts.can_view_all_sessions", "accounts.can_terminate_sessions",
                "accounts.can_view_all_activities",
            ]
        },
        "admin": {
            "name": "Administrator",
            "description": "Has access to user and role management",
            "permissions": [
                "accounts.add_user", "accounts.change_user", "accounts.view_user",
                "accounts.view_role", "accounts.add_userrole", "accounts.delete_userrole",
                "accounts.change_profile", "accounts.view_profile",
                "accounts.can_manage_users", "accounts.can_assign_roles",
                "accounts.can_view_all_profiles", "accounts.can_view_all_sessions",
            ]
        },
        "manager": {
            "name": "Manager",
            "description": "Has access to user management",
            "permissions": [
                "accounts.view_user", "accounts.view_role",
                "accounts.view_profile", "accounts.can_view_user_details",
            ]
        },
        "user": {
            "name": "Regular User",
            "description": "Basic user permissions",
            "permissions": [
                "accounts.view_profile", "accounts.change_profile",
            ]
        }
    }
    
    for role_code, role_data in default_roles.items():
        role, created = Role.objects.get_or_create(
            code=role_code,
            defaults={
                "name": role_data["name"],
                "description": role_data["description"],
                "role_type": "system",
                "level": 1 if role_code == "super_admin" else 2 if role_code == "admin" else 3 if role_code == "manager" else 4,
                "is_active": True,
                "is_default": role_code == "user"
            }
        )
        
        if created:
            print(f"Created role: {role_code}")
            
            # Add permissions to role
            permissions = Permission.objects.filter(codename__in=[
                perm.split(".")[-1] for perm in role_data["permissions"]
            ])
            role.permissions.set(permissions)
            print(f"Added {permissions.count()} permissions to {role_code}")


def has_user_management_permission(user):
    """Check if user has any user management permissions."""
    return user.has_perms([
        UserManagementPermissions.CAN_VIEW_USERS,
        UserManagementPermissions.CAN_ADD_USERS,
        UserManagementPermissions.CAN_CHANGE_USERS,
    ])


def has_role_management_permission(user):
    """Check if user has any role management permissions."""
    return user.has_perms([
        UserManagementPermissions.CAN_VIEW_ROLES,
        UserManagementPermissions.CAN_ADD_ROLES,
        UserManagementPermissions.CAN_CHANGE_ROLES,
    ])


 
