"""
Production-safe deployment script for branch and portfolio filtering
This script safely deploys the filtering system to production
"""
import os
import sys
import shutil
from datetime import datetime


def create_backup():
    """Create backup of files before modification"""
    print("\n" + "="*60)
    print("CREATING BACKUP")
    print("="*60)
    
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    backup_dir = f'backup_before_filtering_{timestamp}'
    
    files_to_backup = [
        'reports/views.py',
        'loans/views.py',
        'utils/views.py',
        'users/views.py',
    ]
    
    try:
        os.makedirs(backup_dir, exist_ok=True)
        
        for file_path in files_to_backup:
            if os.path.exists(file_path):
                # Create directory structure in backup
                backup_file_path = os.path.join(backup_dir, file_path)
                os.makedirs(os.path.dirname(backup_file_path), exist_ok=True)
                
                # Copy file
                shutil.copy2(file_path, backup_file_path)
                print(f"✓ Backed up: {file_path}")
            else:
                print(f"⚠ File not found: {file_path}")
        
        print(f"\n✓ Backup created in: {backup_dir}")
        return backup_dir
        
    except Exception as e:
        print(f"\n✗ Backup failed: {e}")
        return None


def verify_prerequisites():
    """Verify all required files exist"""
    print("\n" + "="*60)
    print("VERIFYING PREREQUISITES")
    print("="*60)
    
    required_files = [
        'utils/filtering.py',  # The new filtering module
        'reports/views.py',
        'loans/views.py',
        'utils/views.py',
    ]
    
    all_exist = True
    
    for file_path in required_files:
        if os.path.exists(file_path):
            print(f"✓ Found: {file_path}")
        else:
            print(f"✗ Missing: {file_path}")
            all_exist = False
    
    return all_exist


def check_django_setup():
    """Check if Django can be imported and setup"""
    print("\n" + "="*60)
    print("CHECKING DJANGO SETUP")
    print("="*60)
    
    try:
        import django
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
        django.setup()
        print("✓ Django setup successful")
        return True
    except Exception as e:
        print(f"✗ Django setup failed: {e}")
        return False


def verify_filtering_module():
    """Verify the filtering module can be imported"""
    print("\n" + "="*60)
    print("VERIFYING FILTERING MODULE")
    print("="*60)
    
    try:
        from utils.filtering import (
            apply_branch_and_portfolio_filters,
            get_filtered_clients,
            get_filtered_loans,
            get_filtered_applications,
            get_filtered_repayments
        )
        print("✓ Filtering module imports successfully")
        print("✓ All required functions available")
        return True
    except ImportError as e:
        print(f"✗ Cannot import filtering module: {e}")
        return False
    except Exception as e:
        print(f"✗ Error verifying filtering module: {e}")
        return False


def test_filtering_with_real_data():
    """Test filtering with actual database data"""
    print("\n" + "="*60)
    print("TESTING FILTERING WITH REAL DATA")
    print("="*60)
    
    try:
        from users.models import CustomUser
        from utils.filtering import get_filtered_clients, get_filtered_loans
        
        # Test with different user types
        test_roles = ['admin', 'loan_officer', 'secretary']
        
        for role in test_roles:
            user = CustomUser.objects.filter(role=role, is_active=True).first()
            if user:
                clients = get_filtered_clients(user)
                loans = get_filtered_loans(user)
                print(f"✓ {role.title()}: {clients.count()} clients, {loans.count()} loans")
            else:
                print(f"⚠ No {role} user found for testing")
        
        return True
        
    except Exception as e:
        print(f"✗ Testing failed: {e}")
        import traceback
        traceback.print_exc()
        return False


def apply_filtering_updates():
    """Apply the filtering updates to view files"""
    print("\n" + "="*60)
    print("APPLYING FILTERING UPDATES")
    print("="*60)
    
    try:
        # Import and run the update script
        import apply_comprehensive_filtering
        
        # Run the main function
        apply_comprehensive_filtering.main()
        
        return True
        
    except Exception as e:
        print(f"✗ Failed to apply updates: {e}")
        import traceback
        traceback.print_exc()
        return False


def run_verification_tests():
    """Run comprehensive verification tests"""
    print("\n" + "="*60)
    print("RUNNING VERIFICATION TESTS")
    print("="*60)
    
    try:
        import verify_filtering_implementation
        verify_filtering_implementation.main()
        return True
    except Exception as e:
        print(f"✗ Verification tests failed: {e}")
        return False


def restart_application():
    """Instructions to restart the application"""
    print("\n" + "="*60)
    print("APPLICATION RESTART REQUIRED")
    print("="*60)
    print("\nTo apply changes in production, restart your application:")
    print("\nFor cPanel:")
    print("  1. Go to cPanel > Setup Python App")
    print("  2. Click 'Restart' button")
    print("\nFor systemd:")
    print("  sudo systemctl restart branch-system")
    print("\nFor Apache:")
    print("  sudo systemctl restart apache2")
    print("\nFor touch reload (if configured):")
    print("  touch tmp/restart.txt")


def rollback(backup_dir):
    """Rollback changes if something goes wrong"""
    print("\n" + "="*60)
    print("ROLLING BACK CHANGES")
    print("="*60)
    
    if not backup_dir or not os.path.exists(backup_dir):
        print("✗ No backup directory found, cannot rollback")
        return False
    
    try:
        files_to_restore = [
            'reports/views.py',
            'loans/views.py',
            'utils/views.py',
            'users/views.py',
        ]
        
        for file_path in files_to_restore:
            backup_file = os.path.join(backup_dir, file_path)
            if os.path.exists(backup_file):
                shutil.copy2(backup_file, file_path)
                print(f"✓ Restored: {file_path}")
        
        print("\n✓ Rollback complete")
        return True
        
    except Exception as e:
        print(f"\n✗ Rollback failed: {e}")
        return False


def main():
    print("\n" + "="*70)
    print("PRODUCTION DEPLOYMENT: BRANCH & PORTFOLIO FILTERING")
    print("="*70)
    
    print("\n⚠ WARNING: This will modify your production system")
    print("⚠ Ensure you have a database backup before proceeding")
    
    response = input("\nDo you want to continue? (yes/no): ").strip().lower()
    
    if response != 'yes':
        print("\n✗ Deployment cancelled by user")
        return
    
    backup_dir = None
    
    try:
        # Step 1: Verify prerequisites
        if not verify_prerequisites():
            print("\n✗ Prerequisites check failed")
            print("Please ensure all required files are present")
            return
        
        # Step 2: Create backup
        backup_dir = create_backup()
        if not backup_dir:
            print("\n✗ Backup failed, aborting deployment")
            return
        
        # Step 3: Check Django setup
        if not check_django_setup():
            print("\n✗ Django setup failed")
            print("Please check your Django configuration")
            return
        
        # Step 4: Verify filtering module
        if not verify_filtering_module():
            print("\n✗ Filtering module verification failed")
            return
        
        # Step 5: Test with real data
        if not test_filtering_with_real_data():
            print("\n✗ Real data testing failed")
            response = input("\nDo you want to continue anyway? (yes/no): ").strip().lower()
            if response != 'yes':
                print("\n✗ Deployment cancelled")
                return
        
        # Step 6: Apply updates
        print("\n" + "="*60)
        print("APPLYING UPDATES")
        print("="*60)
        print("\nThis will modify your view files...")
        
        response = input("Continue? (yes/no): ").strip().lower()
        if response != 'yes':
            print("\n✗ Deployment cancelled")
            return
        
        if not apply_filtering_updates():
            print("\n✗ Failed to apply updates")
            response = input("\nDo you want to rollback? (yes/no): ").strip().lower()
            if response == 'yes':
                rollback(backup_dir)
            return
        
        # Step 7: Run verification tests
        if not run_verification_tests():
            print("\n⚠ Verification tests had issues")
            response = input("\nDo you want to rollback? (yes/no): ").strip().lower()
            if response == 'yes':
                rollback(backup_dir)
                return
        
        # Success!
        print("\n" + "="*70)
        print("✓ DEPLOYMENT SUCCESSFUL")
        print("="*70)
        
        print(f"\n✓ Backup saved in: {backup_dir}")
        print("✓ Filtering system deployed successfully")
        print("✓ All verification tests passed")
        
        restart_application()
        
        print("\n" + "="*70)
        print("POST-DEPLOYMENT CHECKLIST")
        print("="*70)
        print("\n1. [ ] Restart the application")
        print("2. [ ] Test login with different user roles:")
        print("       - Admin user")
        print("       - Loan officer")
        print("       - Secretary/Auditor")
        print("3. [ ] Verify dashboard shows correct filtered data")
        print("4. [ ] Test all reports with different users")
        print("5. [ ] Verify branch selector works correctly")
        print("6. [ ] Check that staff can only see authorized data")
        print("7. [ ] Monitor error logs for any issues")
        
        print("\n" + "="*70)
        print("ROLLBACK INSTRUCTIONS (if needed)")
        print("="*70)
        print(f"\nIf you need to rollback, run:")
        print(f"  python deploy_filtering_to_production.py --rollback {backup_dir}")
        
        print("\n✓ Deployment complete!")
        
    except KeyboardInterrupt:
        print("\n\n✗ Deployment interrupted by user")
        if backup_dir:
            response = input("\nDo you want to rollback? (yes/no): ").strip().lower()
            if response == 'yes':
                rollback(backup_dir)
    
    except Exception as e:
        print(f"\n✗ Deployment failed with error: {e}")
        import traceback
        traceback.print_exc()
        
        if backup_dir:
            response = input("\nDo you want to rollback? (yes/no): ").strip().lower()
            if response == 'yes':
                rollback(backup_dir)


if __name__ == '__main__':
    # Check for rollback flag
    if len(sys.argv) > 1 and sys.argv[1] == '--rollback':
        if len(sys.argv) > 2:
            backup_dir = sys.argv[2]
            rollback(backup_dir)
        else:
            print("Usage: python deploy_filtering_to_production.py --rollback <backup_dir>")
    else:
        main()
