from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse
from django.db import transaction
from django.core.paginator import Paginator
from django.db.models import Q, Count
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
import json

from .models import CustomUser, RolePermission, DefaultRolePermission, UserPermission
from .decorators import admin_required


@login_required
@admin_required
def staff_management_dashboard(request):
    """Enhanced staff management dashboard with comprehensive stats"""
    
    # Get staff statistics
    staff_stats = {
        'total_staff': CustomUser.objects.filter(role__in=['admin', 'team_leader', 'loan_officer', 'secretary']).count(),
        'active_staff': CustomUser.objects.filter(role__in=['admin', 'team_leader', 'loan_officer', 'secretary'], status='active').count(),
        'suspended_staff': CustomUser.objects.filter(role__in=['admin', 'team_leader', 'loan_officer', 'secretary'], status='suspended').count(),
        'admin_count': CustomUser.objects.filter(role='admin').count(),
        'team_leader_count': CustomUser.objects.filter(role='team_leader').count(),
        'loan_officer_count': CustomUser.objects.filter(role='loan_officer').count(),
        'secretary_count': CustomUser.objects.filter(role='secretary').count(),
    }
    
    # Get recent staff activities
    recent_activities = []
    try:
        from .models import UserAccessLog
        recent_activities = UserAccessLog.objects.filter(
            user__role__in=['admin', 'team_leader', 'loan_officer', 'secretary']
        ).select_related('user').order_by('-accessed_at')[:10]
    except ImportError:
        pass
    
    # Get permission summary
    permission_summary = {}
    for role_choice in CustomUser.ROLE_CHOICES:
        if role_choice[0] in ['admin', 'team_leader', 'loan_officer', 'secretary']:
            role = role_choice[0]
            permission_summary[role] = {
                'total_permissions': RolePermission.objects.filter(role=role).count(),
                'allowed_permissions': RolePermission.objects.filter(role=role, is_allowed=True).count(),
                'custom_permissions': UserPermission.objects.filter(user__role=role).count(),
            }
    
    context = {
        'staff_stats': staff_stats,
        'recent_activities': recent_activities,
        'permission_summary': permission_summary,
    }
    
    return render(request, 'users/staff_dashboard.html', context)


@login_required
@admin_required
def default_permissions_management(request):
    """Manage default permissions for each role"""
    
    if request.method == 'POST':
        role = request.POST.get('role')
        if not role:
            messages.error(request, 'Role is required.')
            return redirect('users:default_permissions')
        
        try:
            with transaction.atomic():
                # Update default permissions
                for module_choice in RolePermission.MODULE_CHOICES:
                    module = module_choice[0]
                    for action_choice in RolePermission.ACTION_CHOICES:
                        action = action_choice[0]
                        is_allowed = request.POST.get(f'default_{role}_{module}_{action}') == 'on'
                        
                        # Update or create default permission
                        default_perm, created = DefaultRolePermission.objects.get_or_create(
                            role=role,
                            module=module,
                            action=action,
                            defaults={'is_allowed': is_allowed}
                        )
                        
                        if not created and default_perm.is_allowed != is_allowed:
                            default_perm.is_allowed = is_allowed
                            default_perm.save()
                        
                        # Update role permission
                        role_perm, created = RolePermission.objects.get_or_create(
                            role=role,
                            module=module,
                            action=action,
                            defaults={'is_allowed': is_allowed, 'is_default': True}
                        )
                        
                        if not created and role_perm.is_default and role_perm.is_allowed != is_allowed:
                            role_perm.is_allowed = is_allowed
                            role_perm.save()
                
                messages.success(request, f'Default permissions updated for {role.replace("_", " ").title()} role.')
                
        except Exception as e:
            messages.error(request, f'Error updating default permissions: {str(e)}')
    
    # Get current default permissions
    default_permissions = {}
    staff_roles = ['admin', 'team_leader', 'loan_officer', 'secretary']
    
    for role in staff_roles:
        default_permissions[role] = {}
        for module_choice in RolePermission.MODULE_CHOICES:
            module = module_choice[0]
            default_permissions[role][module] = {}
            for action_choice in RolePermission.ACTION_CHOICES:
                action = action_choice[0]
                try:
                    default_perm = DefaultRolePermission.objects.get(role=role, module=module, action=action)
                    default_permissions[role][module][action] = default_perm.is_allowed
                except DefaultRolePermission.DoesNotExist:
                    default_permissions[role][module][action] = False
    
    context = {
        'default_permissions': default_permissions,
        'staff_roles': staff_roles,
        'modules': RolePermission.MODULE_CHOICES,
        'actions': RolePermission.ACTION_CHOICES,
    }
    
    return render(request, 'users/default_permissions.html', context)


@login_required
@admin_required
def staff_permissions_detail(request, user_id):
    """Detailed permission management for individual staff member"""
    
    user = get_object_or_404(CustomUser, id=user_id)
    
    if user.role not in ['admin', 'team_leader', 'loan_officer', 'secretary']:
        messages.error(request, 'This user is not a staff member.')
        return redirect('users:staff_list')
    
    if request.method == 'POST':
        try:
            with transaction.atomic():
                # Handle custom permissions
                for module_choice in RolePermission.MODULE_CHOICES:
                    module = module_choice[0]
                    for action_choice in RolePermission.ACTION_CHOICES:
                        action = action_choice[0]
                        
                        # Check if custom permission is set
                        custom_key = f'custom_{module}_{action}'
                        use_custom = request.POST.get(custom_key) == 'on'
                        
                        if use_custom:
                            # Create or update custom permission
                            is_allowed = request.POST.get(f'perm_{module}_{action}') == 'on'
                            reason = request.POST.get(f'reason_{module}_{action}', '')
                            
                            user_perm, created = UserPermission.objects.get_or_create(
                                user=user,
                                module=module,
                                action=action,
                                defaults={
                                    'is_allowed': is_allowed,
                                    'granted_by': request.user,
                                    'reason': reason
                                }
                            )
                            
                            if not created:
                                user_perm.is_allowed = is_allowed
                                user_perm.granted_by = request.user
                                user_perm.reason = reason
                                user_perm.save()
                        else:
                            # Remove custom permission if exists
                            UserPermission.objects.filter(user=user, module=module, action=action).delete()
                
                messages.success(request, f'Permissions updated for {user.get_full_name()}.')
                
        except Exception as e:
            messages.error(request, f'Error updating permissions: {str(e)}')
    
    # Get effective permissions
    effective_permissions = user.get_effective_permissions()
    
    # Get default permissions for comparison
    default_permissions = {}
    for module_choice in RolePermission.MODULE_CHOICES:
        module = module_choice[0]
        default_permissions[module] = {}
        for action_choice in RolePermission.ACTION_CHOICES:
            action = action_choice[0]
            try:
                default_perm = DefaultRolePermission.objects.get(role=user.role, module=module, action=action)
                default_permissions[module][action] = default_perm.is_allowed
            except DefaultRolePermission.DoesNotExist:
                default_permissions[module][action] = False
    
    context = {
        'user': user,
        'effective_permissions': effective_permissions,
        'default_permissions': default_permissions,
        'modules': RolePermission.MODULE_CHOICES,
        'actions': RolePermission.ACTION_CHOICES,
    }
    
    return render(request, 'users/staff_permissions_detail.html', context)


@login_required
@admin_required
def apply_default_permissions(request, user_id):
    """Apply default permissions to a user"""
    
    user = get_object_or_404(CustomUser, id=user_id)
    
    if request.method == 'POST':
        try:
            with transaction.atomic():
                # Remove all custom permissions
                UserPermission.objects.filter(user=user).delete()
                
                # Apply default permissions
                default_permissions = DefaultRolePermission.objects.filter(role=user.role)
                for default_perm in default_permissions:
                    role_perm, created = RolePermission.objects.get_or_create(
                        role=user.role,
                        module=default_perm.module,
                        action=default_perm.action,
                        defaults={
                            'is_allowed': default_perm.is_allowed,
                            'is_default': True
                        }
                    )
                    
                    if not created:
                        role_perm.is_allowed = default_perm.is_allowed
                        role_perm.is_default = True
                        role_perm.save()
                
                messages.success(request, f'Default permissions applied to {user.get_full_name()}.')
                
        except Exception as e:
            messages.error(request, f'Error applying default permissions: {str(e)}')
    
    return redirect('users:staff_permissions_detail', user_id=user_id)


@login_required
@admin_required
def bulk_permission_update(request):
    """Bulk update permissions for multiple staff members"""
    
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            user_ids = data.get('user_ids', [])
            permissions = data.get('permissions', {})
            action_type = data.get('action_type', 'update')  # update, apply_defaults, remove_custom
            
            users = CustomUser.objects.filter(id__in=user_ids, role__in=['admin', 'team_leader', 'loan_officer', 'secretary'])
            
            with transaction.atomic():
                for user in users:
                    if action_type == 'apply_defaults':
                        # Remove custom permissions and apply defaults
                        UserPermission.objects.filter(user=user).delete()
                        
                    elif action_type == 'remove_custom':
                        # Remove only custom permissions
                        UserPermission.objects.filter(user=user).delete()
                        
                    elif action_type == 'update':
                        # Update specific permissions
                        for module, actions in permissions.items():
                            for action, is_allowed in actions.items():
                                user_perm, created = UserPermission.objects.get_or_create(
                                    user=user,
                                    module=module,
                                    action=action,
                                    defaults={
                                        'is_allowed': is_allowed,
                                        'granted_by': request.user,
                                        'reason': f'Bulk update by {request.user.get_full_name()}'
                                    }
                                )
                                
                                if not created:
                                    user_perm.is_allowed = is_allowed
                                    user_perm.granted_by = request.user
                                    user_perm.save()
            
            return JsonResponse({
                'success': True,
                'message': f'Permissions updated for {users.count()} staff members.'
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })
    
    return JsonResponse({'success': False, 'error': 'Invalid request method.'})


@login_required
@admin_required
def permission_templates(request):
    """Manage permission templates for quick assignment"""
    
    if request.method == 'POST':
        template_name = request.POST.get('template_name')
        template_role = request.POST.get('template_role')
        
        if not template_name or not template_role:
            messages.error(request, 'Template name and role are required.')
            return redirect('users:permission_templates')
        
        # Save template permissions
        template_permissions = {}
        for module_choice in RolePermission.MODULE_CHOICES:
            module = module_choice[0]
            template_permissions[module] = {}
            for action_choice in RolePermission.ACTION_CHOICES:
                action = action_choice[0]
                template_permissions[module][action] = request.POST.get(f'template_{module}_{action}') == 'on'
        
        # Store template in session or database (implement as needed)
        request.session[f'permission_template_{template_name}'] = {
            'role': template_role,
            'permissions': template_permissions
        }
        
        messages.success(request, f'Permission template "{template_name}" saved.')
    
    # Get saved templates
    templates = {}
    for key, value in request.session.items():
        if key.startswith('permission_template_'):
            template_name = key.replace('permission_template_', '')
            templates[template_name] = value
    
    context = {
        'templates': templates,
        'modules': RolePermission.MODULE_CHOICES,
        'actions': RolePermission.ACTION_CHOICES,
        'staff_roles': ['admin', 'team_leader', 'loan_officer', 'secretary'],
    }
    
    return render(request, 'users/permission_templates.html', context)


@login_required
@admin_required
def permission_audit_log(request):
    """View permission change audit log"""
    
    # Get permission changes from access logs
    permission_changes = []
    try:
        from .models import UserAccessLog
        permission_changes = UserAccessLog.objects.filter(
            action__in=['update_permissions', 'create_user', 'apply_defaults']
        ).select_related('user').order_by('-accessed_at')
        
        # Paginate results
        paginator = Paginator(permission_changes, 25)
        page_number = request.GET.get('page')
        permission_changes = paginator.get_page(page_number)
        
    except ImportError:
        pass
    
    context = {
        'permission_changes': permission_changes,
    }
    
    return render(request, 'users/permission_audit_log.html', context)


@login_required
@admin_required
@require_http_methods(["GET"])
def get_role_permissions(request, role):
    """AJAX endpoint to get permissions for a specific role"""
    
    try:
        permissions = {}
        for module_choice in RolePermission.MODULE_CHOICES:
            module = module_choice[0]
            permissions[module] = {}
            for action_choice in RolePermission.ACTION_CHOICES:
                action = action_choice[0]
                try:
                    default_perm = DefaultRolePermission.objects.get(role=role, module=module, action=action)
                    permissions[module][action] = default_perm.is_allowed
                except DefaultRolePermission.DoesNotExist:
                    permissions[module][action] = False
        
        return JsonResponse({
            'success': True,
            'permissions': permissions
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


@login_required
@admin_required
def copy_permissions(request, from_user_id, to_user_id):
    """Copy permissions from one user to another"""
    
    from_user = get_object_or_404(CustomUser, id=from_user_id)
    to_user = get_object_or_404(CustomUser, id=to_user_id)
    
    if request.method == 'POST':
        try:
            with transaction.atomic():
                # Remove existing custom permissions for target user
                UserPermission.objects.filter(user=to_user).delete()
                
                # Copy custom permissions from source user
                source_permissions = UserPermission.objects.filter(user=from_user)
                for perm in source_permissions:
                    UserPermission.objects.create(
                        user=to_user,
                        module=perm.module,
                        action=perm.action,
                        is_allowed=perm.is_allowed,
                        granted_by=request.user,
                        reason=f'Copied from {from_user.get_full_name()}'
                    )
                
                messages.success(request, f'Permissions copied from {from_user.get_full_name()} to {to_user.get_full_name()}.')
                
        except Exception as e:
            messages.error(request, f'Error copying permissions: {str(e)}')
    
    return redirect('users:staff_permissions_detail', user_id=to_user_id)