#!/usr/bin/env python
"""
Test script for enhanced role template application logic
Tests task 6.2: Implement role template application logic
"""

import os
import sys
import django
from django.conf import settings

# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
django.setup()

from django.test import TestCase
from django.contrib.auth import get_user_model
from users.models import CustomUser, Branch
from users.enhanced_permissions_models import PagePermission, RolePermissionTemplate, UserPagePermission, RoleTemplateRollbackPoint
from users.services import RolePermissionTemplateManager
from django.db import transaction
import json

def test_role_template_application_logic():
    """Test the enhanced role template application logic"""
    
    print("🧪 Testing Enhanced Role Template Application Logic")
    print("=" * 60)
    
    try:
        # Clean up existing test data
        print("\n1. Cleaning up existing test data...")
        CustomUser.objects.filter(username__startswith='test_').delete()
        PagePermission.objects.filter(page_name='test_page').delete()
        RolePermissionTemplate.objects.filter(role='loan_officer').delete()
        RoleTemplateRollbackPoint.objects.all().delete()
        
        # Create test branch
        branch, _ = Branch.objects.get_or_create(
            name='Test Branch',
            defaults={'location': 'Test Location'}
        )
        
        # Create test users
        print("\n2. Creating test users...")
        admin_user = CustomUser.objects.create_user(
            username='test_admin',
            email='admin@test.com',
            password='testpass123',
            role='admin',
            branch=branch,
            is_superuser=True,
            phone_number='0700000001'
        )
        
        loan_officer = CustomUser.objects.create_user(
            username='test_loan_officer',
            email='officer@test.com',
            password='testpass123',
            role='loan_officer',
            branch=branch,
            phone_number='0700000002'
        )
        
        print(f"✓ Created admin user: {admin_user.get_full_name()}")
        print(f"✓ Created loan officer: {loan_officer.get_full_name()}")
        
        # Create test permissions
        print("\n3. Creating test permissions...")
        test_permissions = [
            {
                'page_name': 'test_page',
                'action_code': 'test_view',
                'action_name': 'View Test Page',
                'description': 'Permission to view test page',
                'category': 'view',
                'is_critical': False
            },
            {
                'page_name': 'test_page',
                'action_code': 'test_edit',
                'action_name': 'Edit Test Page',
                'description': 'Permission to edit test page',
                'category': 'edit',
                'is_critical': True
            },
            {
                'page_name': 'test_page',
                'action_code': 'test_delete',
                'action_name': 'Delete Test Items',
                'description': 'Permission to delete test items',
                'category': 'delete',
                'is_critical': True
            }
        ]
        
        created_permissions = []
        for perm_data in test_permissions:
            permission = PagePermission.objects.create(**perm_data)
            created_permissions.append(permission)
            print(f"✓ Created permission: {permission.action_name}")
        
        # Initialize role template manager
        template_manager = RolePermissionTemplateManager()
        
        # Test 1: Create role template
        print("\n4. Testing role template creation...")
        permissions_dict = {
            'test_page': {
                'test_view': True,
                'test_edit': False,
                'test_delete': False
            }
        }
        
        result = template_manager.set_role_defaults(
            role='loan_officer',
            permissions_dict=permissions_dict,
            created_by=admin_user
        )
        
        if result['success']:
            print(f"✓ Role template created successfully")
            print(f"  - Total permissions: {result['total_permissions']}")
            print(f"  - Created permissions: {result['created_permissions']}")
            print(f"  - Updated permissions: {result['updated_permissions']}")
        else:
            print(f"✗ Failed to create role template: {result.get('error')}")
            return False
        
        # Test 2: Apply role template to user
        print("\n5. Testing role template application to user...")
        apply_result = template_manager.apply_role_template_to_user(
            user=loan_officer,
            role_template='loan_officer',
            update_existing=False,
            conflict_resolution='keep_custom',
            applied_by=admin_user
        )
        
        if apply_result['success']:
            print(f"✓ Role template applied successfully")
            print(f"  - Permissions applied: {apply_result['permissions_applied']}")
            print(f"  - Permissions skipped: {apply_result['permissions_skipped']}")
            print(f"  - Conflicts resolved: {apply_result['conflicts_resolved']}")
            if apply_result.get('approval_required'):
                print(f"  - Approval required: Yes")
                print(f"  - Critical changes: {len(apply_result.get('critical_changes', []))}")
        else:
            print(f"✗ Failed to apply role template: {apply_result.get('error')}")
            return False
        
        # Test 3: Create custom permission conflict
        print("\n6. Testing conflict resolution...")
        # Create a custom permission that conflicts with role template
        custom_permission = UserPagePermission.objects.create(
            user=loan_officer,
            page_permission=created_permissions[1],  # test_edit
            is_allowed=True,  # Conflicts with role template (False)
            reason="Custom override for testing"
        )
        print(f"✓ Created conflicting custom permission: {custom_permission}")
        
        # Apply template again with different conflict resolution
        conflict_result = template_manager.apply_role_template_to_user(
            user=loan_officer,
            role_template='loan_officer',
            update_existing=True,
            conflict_resolution='use_role',
            applied_by=admin_user
        )
        
        if conflict_result['success']:
            print(f"✓ Conflict resolution completed")
            print(f"  - Conflicts resolved: {conflict_result['conflicts_resolved']}")
            for conflict in conflict_result.get('conflicts', []):
                print(f"    - {conflict['permission_code']}: {conflict['action_taken']}")
        
        # Test 4: Bulk update functionality
        print("\n7. Testing bulk update functionality...")
        # Create additional test users
        bulk_users = []
        for i in range(3):
            user = CustomUser.objects.create_user(
                username=f'test_bulk_user_{i}',
                email=f'bulk{i}@test.com',
                password='testpass123',
                role='loan_officer',
                branch=branch,
                phone_number=f'070000001{i}'
            )
            bulk_users.append(user)
        
        user_ids = [str(user.id) for user in bulk_users]
        bulk_result = template_manager.bulk_update_users_with_template(
            user_ids=user_ids,
            role='loan_officer',
            update_existing=True,
            conflict_resolution='use_role',
            applied_by=admin_user,
            batch_size=2
        )
        
        if bulk_result['success']:
            print(f"✓ Bulk update completed successfully")
            print(f"  - Total users: {bulk_result['total_users']}")
            print(f"  - Users processed: {bulk_result['users_processed']}")
            print(f"  - Permissions applied: {bulk_result['permissions_applied']}")
            print(f"  - Processing time: {bulk_result['processing_time']:.2f}s")
            print(f"  - Batches processed: {bulk_result['batches_processed']}")
        else:
            print(f"✗ Bulk update failed: {bulk_result.get('error')}")
        
        # Test 5: Rollback functionality
        print("\n8. Testing rollback functionality...")
        # Create rollback point
        rollback_id = template_manager.create_template_rollback_point(
            role='loan_officer',
            created_by=admin_user,
            description="Test rollback point"
        )
        
        if rollback_id:
            print(f"✓ Rollback point created: {rollback_id}")
            
            # Verify rollback point was stored in database
            rollback_point = RoleTemplateRollbackPoint.objects.get(rollback_id=rollback_id)
            summary = rollback_point.get_template_summary()
            print(f"  - Template summary: {summary}")
            
            # Modify the template
            modified_permissions = {
                'test_page': {
                    'test_view': True,
                    'test_edit': True,  # Changed from False
                    'test_delete': True  # Changed from False
                }
            }
            
            template_manager.set_role_defaults(
                role='loan_officer',
                permissions_dict=modified_permissions,
                created_by=admin_user
            )
            print("✓ Modified role template")
            
            # Test rollback
            rollback_result = template_manager.rollback_template_changes(
                rollback_id=rollback_id,
                applied_by=admin_user
            )
            
            if rollback_result['success']:
                print(f"✓ Rollback completed successfully")
                print(f"  - Permissions restored: {rollback_result['permissions_restored']}")
                print(f"  - New rollback ID: {rollback_result.get('new_rollback_id')}")
            else:
                print(f"✗ Rollback failed: {rollback_result.get('error')}")
        
        # Test 6: Approval workflow
        print("\n9. Testing approval workflow...")
        # Create permissions that require approval
        critical_permissions = {
            'test_page': {
                'test_view': True,
                'test_edit': True,  # Critical permission
                'test_delete': True  # Critical permission
            }
        }
        
        approval_result = template_manager.create_permission_change_approval_request(
            user=loan_officer,
            role='loan_officer',
            permissions_dict=critical_permissions,
            requested_by=admin_user,
            reason="Testing approval workflow"
        )
        
        if approval_result['success']:
            if approval_result['approval_required']:
                print(f"✓ Approval workflow triggered")
                print(f"  - Request ID: {approval_result['request_id']}")
                print(f"  - Approvers needed: {approval_result['approvers_needed']}")
                print(f"  - Critical permissions: {len(approval_result['critical_permissions'])}")
                
                # Test approval processing
                if approval_result['approvers_needed']:
                    process_result = template_manager.process_permission_approval(
                        request_id=approval_result['request_id'],
                        approver=admin_user,
                        decision='approve',
                        comments='Approved for testing'
                    )
                    
                    if process_result['success']:
                        print(f"✓ Approval processed: {process_result['decision']}")
                        if process_result['decision'] == 'approved_and_applied':
                            print(f"  - Permissions applied: {process_result.get('permissions_applied', 0)}")
                    else:
                        print(f"✗ Approval processing failed: {process_result.get('error')}")
            else:
                print(f"✓ No approval required, changes applied directly")
        else:
            print(f"✗ Approval workflow failed: {approval_result.get('error')}")
        
        # Test 7: Get available rollback points
        print("\n10. Testing rollback point retrieval...")
        rollback_points = template_manager.get_available_rollback_points('loan_officer')
        print(f"✓ Found {len(rollback_points)} rollback points")
        for point in rollback_points:
            print(f"  - {point['rollback_id']}: {point['description']}")
        
        print("\n" + "=" * 60)
        print("🎉 All role template application logic tests completed successfully!")
        print("\nImplemented features:")
        print("✓ Enhanced role template application with conflict resolution")
        print("✓ Bulk update functionality with progress tracking")
        print("✓ Database-backed rollback functionality")
        print("✓ Approval workflow for sensitive permission changes")
        print("✓ Comprehensive validation and error handling")
        
        return True
        
    except Exception as e:
        print(f"\n❌ Test failed with error: {e}")
        import traceback
        traceback.print_exc()
        return False
    
    finally:
        # Clean up test data
        print("\n11. Cleaning up test data...")
        try:
            CustomUser.objects.filter(username__startswith='test_').delete()
            PagePermission.objects.filter(page_name='test_page').delete()
            RolePermissionTemplate.objects.filter(role='loan_officer').delete()
            RoleTemplateRollbackPoint.objects.all().delete()
            print("✓ Test data cleaned up")
        except Exception as e:
            print(f"⚠️  Warning: Could not clean up all test data: {e}")

if __name__ == '__main__':
    success = test_role_template_application_logic()
    sys.exit(0 if success else 1)