#!/usr/bin/env python3
"""
Fix Missing Field Error

This script fixes the KeyError: 'is_default' error by handling the migration
state properly and ensuring all fields exist before trying to remove them.

Usage:
    python fix_missing_field_error.py
"""

import os
import sys
import django
import subprocess
from pathlib import Path

def setup_django():
    """Setup Django environment"""
    try:
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
        django.setup()
        print("[SUCCESS] Django environment setup successful")
        return True
    except Exception as e:
        print(f"[ERROR] Django setup failed: {str(e)}")
        return False

def check_migration_status():
    """Check current migration status"""
    try:
        result = subprocess.run([
            'python', 'manage.py', 'showmigrations', 'users'
        ], capture_output=True, text=True, cwd=Path.cwd())
        
        if result.returncode == 0:
            print("Current migration status:")
            print(result.stdout)
            return result.stdout
        else:
            print(f"Error checking migration status: {result.stderr}")
            return None
    except Exception as e:
        print(f"Error checking migration status: {str(e)}")
        return None

def check_table_columns(table_name):
    """Check if a table has specific columns"""
    try:
        from django.db import connection
        with connection.cursor() as cursor:
            cursor.execute(f"DESCRIBE {table_name}")
            columns = cursor.fetchall()
            return [col[0] for col in columns]
    except Exception as e:
        print(f"Error checking table {table_name}: {str(e)}")
        return []

def fix_missing_field_error():
    """Fix the missing field error"""
    print("=" * 60)
    print("FIXING MISSING FIELD ERROR")
    print("=" * 60)
    
    if not setup_django():
        return False
    
    # Step 1: Check current migration status
    print("Step 1: Checking migration status...")
    migration_status = check_migration_status()
    
    # Step 2: Check database tables
    print("Step 2: Checking database tables...")
    
    # Check if user_permissions table exists
    user_perms_columns = check_table_columns('user_permissions')
    if user_perms_columns:
        print(f"user_permissions table exists with columns: {user_perms_columns}")
    else:
        print("user_permissions table does not exist")
    
    # Check if rolepermission table exists and has is_default column
    role_perm_columns = check_table_columns('rolepermission')
    if role_perm_columns:
        print(f"rolepermission table has columns: {role_perm_columns}")
        if 'is_default' in role_perm_columns:
            print("[INFO] is_default column exists in rolepermission table")
        else:
            print("[INFO] is_default column does not exist in rolepermission table")
    else:
        print("rolepermission table does not exist")
    
    # Step 3: Handle the problematic migrations
    print("Step 3: Handling problematic migrations...")
    
    # The issue is that migration 0019 is trying to remove is_default field
    # but the field doesn't exist in the current state
    # We need to mark this migration as fake or skip it
    
    # Check if the problematic migration file exists
    problematic_migrations = [
        '0019_remove_rolepermission_role_permis_role_056d99_idx_and_more.py',
        '0019_alter_customuser_role.py'
    ]
    
    for migration_file in problematic_migrations:
        migration_path = Path(f'users/migrations/{migration_file}')
        if migration_path.exists():
            print(f"[INFO] Found problematic migration: {migration_file}")
            
            # Try to mark it as fake
            migration_name = migration_file.replace('.py', '')
            print(f"Attempting to mark {migration_name} as fake...")
            
            try:
                result = subprocess.run([
                    'python', 'manage.py', 'migrate', 'users', migration_name, '--fake'
                ], capture_output=True, text=True, cwd=Path.cwd())
                
                if result.returncode == 0:
                    print(f"[SUCCESS] {migration_name} marked as fake")
                else:
                    print(f"[WARNING] Could not mark {migration_name} as fake: {result.stderr}")
            except Exception as e:
                print(f"[WARNING] Error marking {migration_name} as fake: {str(e)}")
    
    # Step 4: Try to apply migrations again
    print("Step 4: Applying migrations...")
    try:
        result = subprocess.run([
            'python', 'manage.py', 'migrate', 'users'
        ], capture_output=True, text=True, cwd=Path.cwd())
        
        if result.returncode == 0:
            print("[SUCCESS] Migrations applied successfully")
            print(f"Output: {result.stdout}")
        else:
            print(f"[ERROR] Failed to apply migrations: {result.stderr}")
            
            # If it's still the is_default error, try a different approach
            if "KeyError: 'is_default'" in result.stderr:
                print("Still getting is_default error, trying alternative approach...")
                return handle_is_default_error()
            
            return False
            
    except Exception as e:
        print(f"[ERROR] Error applying migrations: {str(e)}")
        return False
    
    # Step 5: Verify the fix
    print("Step 5: Verifying the fix...")
    return verify_fix()

def handle_is_default_error():
    """Handle the is_default error specifically"""
    print("Handling is_default error specifically...")
    
    # Try to reset to a stable migration and then apply forward
    print("Attempting to reset to migration 0017...")
    try:
        result = subprocess.run([
            'python', 'manage.py', 'migrate', 'users', '0017'
        ], capture_output=True, text=True, cwd=Path.cwd())
        
        if result.returncode == 0:
            print("[SUCCESS] Reset to migration 0017")
            
            # Now try to apply migrations forward
            print("Applying migrations forward...")
            result = subprocess.run([
                'python', 'manage.py', 'migrate', 'users'
            ], capture_output=True, text=True, cwd=Path.cwd())
            
            if result.returncode == 0:
                print("[SUCCESS] Migrations applied forward")
                return verify_fix()
            else:
                print(f"[ERROR] Still failed after reset: {result.stderr}")
                return False
        else:
            print(f"[ERROR] Failed to reset to migration 0017: {result.stderr}")
            return False
            
    except Exception as e:
        print(f"[ERROR] Error handling is_default error: {str(e)}")
        return False

def verify_fix():
    """Verify that the fix worked"""
    try:
        from django.db import connection
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM user_permissions WHERE module = 'test'")
            result = cursor.fetchone()
            print("[SUCCESS] user_permissions table is working correctly")
            return True
    except Exception as e:
        print(f"[ERROR] Verification failed: {str(e)}")
        return False

def main():
    """Main function"""
    try:
        success = fix_missing_field_error()
        
        if success:
            print("=" * 60)
            print("MISSING FIELD ERROR FIXED SUCCESSFULLY!")
            print("The user_permissions table should now work correctly.")
            print("=" * 60)
        else:
            print("=" * 60)
            print("FAILED TO FIX MISSING FIELD ERROR")
            print("Please check the error messages above.")
            print("=" * 60)
        
        return success
        
    except Exception as e:
        print(f"Script failed: {str(e)}")
        return False

if __name__ == '__main__':
    success = main()
    sys.exit(0 if success else 1)
