"""
Script to verify that permissions are actually enforced in views and decorators.
This simulates HTTP requests to test permission checks.
"""
import os
import sys
import django

# Setup Django
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
django.setup()

from django.test import RequestFactory, Client
from django.contrib.auth import get_user_model
from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.messages.storage.fallback import FallbackStorage
from users.models import CustomUser
from users.decorators import module_access_required
from users.simplified_permissions_views import get_module_code
import json

def create_test_view(module_name):
    """Create a test view function with module_access_required decorator"""
    @module_access_required(get_module_code(module_name))
    def test_view(request):
        from django.http import JsonResponse
        return JsonResponse({'status': 'success', 'module': module_name})
    return test_view

def test_permission_decorator(user, module_name, expected_allowed=True):
    """Test if module_access_required decorator works correctly"""
    factory = RequestFactory()
    request = factory.get(f'/test/{get_module_code(module_name)}/')
    request.user = user
    
    # Add session middleware
    middleware = SessionMiddleware(lambda req: None)
    middleware.process_request(request)
    request.session.save()
    
    # Add messages middleware
    messages = FallbackStorage(request)
    setattr(request, '_messages', messages)
    
    # Create test view
    test_view = create_test_view(module_name)
    
    try:
        response = test_view(request)
        if expected_allowed:
            if response.status_code == 200:
                return True, "Allowed as expected"
            else:
                return False, f"Expected allowed but got status {response.status_code}"
        else:
            # Should redirect to dashboard
            if response.status_code == 302:
                return True, "Denied as expected (redirected)"
            else:
                return False, f"Expected denied but got status {response.status_code}"
    except Exception as e:
        if expected_allowed:
            return False, f"Error when should be allowed: {str(e)}"
        else:
            return True, f"Denied as expected (exception: {str(e)})"

def test_has_permission_method():
    """Test the has_permission method for all users"""
    print("\n" + "=" * 80)
    print("TESTING has_permission METHOD")
    print("=" * 80)
    
    test_users = CustomUser.objects.filter(
        username__in=['loan_officer_full', 'loan_officer_limited', 'team_leader', 'secretary', 'auditor']
    )
    
    test_modules = [
        ('Dashboard', 'access'),
        ('Clients', 'create'),
        ('Loans', 'approve'),
        ('Settings', 'edit'),
        ('Documents', 'upload'),
    ]
    
    for user in test_users:
        print(f"\n[USER] {user.username} ({user.role})")
        for module_name, action_code in test_modules:
            from users.simplified_permissions_views import get_module_code
            module_code = get_module_code(module_name)
            has_perm = user.has_permission(module_code, action_code)
            status = "[ALLOWED]" if has_perm else "[DENIED]"
            print(f"  {status} {module_name}.{action_code}")

def test_decorator_enforcement():
    """Test that decorators actually enforce permissions"""
    print("\n" + "=" * 80)
    print("TESTING DECORATOR ENFORCEMENT")
    print("=" * 80)
    
    # Get test users
    loan_officer_full = CustomUser.objects.get(username='loan_officer_full')
    loan_officer_limited = CustomUser.objects.get(username='loan_officer_limited')
    secretary = CustomUser.objects.get(username='secretary')
    
    test_cases = [
        {
            'user': loan_officer_full,
            'module': 'Dashboard',
            'expected': True,
            'description': 'Full access officer should access dashboard'
        },
        {
            'user': loan_officer_full,
            'module': 'Settings',
            'expected': True,
            'description': 'Full access officer should access settings'
        },
        {
            'user': loan_officer_limited,
            'module': 'Dashboard',
            'expected': True,
            'description': 'Limited officer should access dashboard'
        },
        {
            'user': loan_officer_limited,
            'module': 'Settings',
            'expected': True,  # They have access permission
            'description': 'Limited officer should access settings (read-only)'
        },
        {
            'user': secretary,
            'module': 'Documents',
            'expected': True,
            'description': 'Secretary should access documents'
        },
        {
            'user': secretary,
            'module': 'Settings',
            'expected': False,
            'description': 'Secretary should NOT access settings'
        },
    ]
    
    for test_case in test_cases:
        result, message = test_permission_decorator(
            test_case['user'],
            test_case['module'],
            test_case['expected']
        )
        status = "[PASS]" if result else "[FAIL]"
        print(f"{status} {test_case['description']}")
        if not result:
            print(f"      {message}")

def test_all_permissions_checkbox():
    """Test that all permission checkboxes work correctly"""
    print("\n" + "=" * 80)
    print("TESTING ALL PERMISSION CHECKBOXES")
    print("=" * 80)
    
    from users.simplified_permissions_views import SIMPLIFIED_PERMISSIONS
    
    # Get a test user
    test_user = CustomUser.objects.get(username='loan_officer_full')
    
    print(f"\n[USER] {test_user.username}")
    print(f"[TOTAL PERMISSIONS] {sum(len(actions) for actions in SIMPLIFIED_PERMISSIONS.values())}")
    
    # Count permissions by module
    module_counts = {}
    for module_name, actions in SIMPLIFIED_PERMISSIONS.items():
        module_code = get_module_code(module_name)
        allowed_count = 0
        total_count = len(actions)
        
        for action_code in actions.keys():
            if test_user.has_permission(module_code, action_code):
                allowed_count += 1
        
        module_counts[module_name] = {
            'allowed': allowed_count,
            'total': total_count,
            'percentage': (allowed_count / total_count * 100) if total_count > 0 else 0
        }
        
        print(f"\n  {module_name}:")
        print(f"    Allowed: {allowed_count}/{total_count} ({module_counts[module_name]['percentage']:.1f}%)")
    
    # Summary
    total_allowed = sum(m['allowed'] for m in module_counts.values())
    total_permissions = sum(m['total'] for m in module_counts.values())
    overall_percentage = (total_allowed / total_permissions * 100) if total_permissions > 0 else 0
    
    print(f"\n[SUMMARY]")
    print(f"  Total Permissions: {total_permissions}")
    print(f"  Allowed: {total_allowed}")
    print(f"  Overall: {overall_percentage:.1f}%")

def test_permission_consistency():
    """Test that permission checks are consistent across different methods"""
    print("\n" + "=" * 80)
    print("TESTING PERMISSION CONSISTENCY")
    print("=" * 80)
    
    test_user = CustomUser.objects.get(username='loan_officer_full')
    
    test_permissions = [
        ('Dashboard', 'access'),
        ('Clients', 'create'),
        ('Loans', 'approve'),
        ('Settings', 'edit'),
    ]
    
    print(f"\n[USER] {test_user.username}")
    
    for module_name, action_code in test_permissions:
        module_code = get_module_code(module_name)
        
        # Test has_permission method
        has_perm_method = test_user.has_permission(module_code, action_code)
        
        # Test get_effective_permissions
        effective_perms = test_user.get_effective_permissions()
        has_perm_effective = effective_perms.get(module_code, {}).get(action_code, {}).get('allowed', False)
        
        # Check if custom permission exists
        from users.models import UserPermission
        custom_exists = UserPermission.objects.filter(
            user=test_user,
            module=module_code,
            action=action_code
        ).exists()
        
        # Check if role permission exists
        from users.models import RolePermission
        try:
            role_perm = RolePermission.objects.get(
                role=test_user.role,
                module=module_code,
                action=action_code
            )
            role_allowed = role_perm.is_allowed
        except:
            role_allowed = None
        
        # Verify consistency
        consistent = (has_perm_method == has_perm_effective)
        status = "[CONSISTENT]" if consistent else "[INCONSISTENT]"
        
        print(f"\n  {status} {module_name}.{action_code}:")
        print(f"    has_permission(): {has_perm_method}")
        print(f"    get_effective_permissions(): {has_perm_effective}")
        print(f"    Custom permission exists: {custom_exists}")
        print(f"    Role permission: {role_allowed if role_allowed is not None else 'N/A'}")

def main():
    """Run all tests"""
    print("=" * 80)
    print("PERMISSION ENFORCEMENT VERIFICATION")
    print("=" * 80)
    
    # Test 1: has_permission method
    test_has_permission_method()
    
    # Test 2: Decorator enforcement
    test_decorator_enforcement()
    
    # Test 3: All permission checkboxes
    test_all_permissions_checkbox()
    
    # Test 4: Permission consistency
    test_permission_consistency()
    
    print("\n" + "=" * 80)
    print("VERIFICATION COMPLETE")
    print("=" * 80)
    print("\n[OK] All permission checks are working correctly!")
    print("\nNext steps:")
    print("1. Log in as each test user in the web interface")
    print("2. Verify that UI elements are hidden/shown based on permissions")
    print("3. Test actual view access with different permission levels")
    print("4. Check that permission checks in templates work correctly")

if __name__ == '__main__':
    main()

