import os
import sys
import django

# Set up Django environment
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
django.setup()

from django.db import connection, migrations, models
import django.db.models.deletion
from django.db.migrations.executor import MigrationExecutor
from django.apps import apps
from django.conf import settings

def fix_notification_models_conflict():
    """
    Fix the conflict between the two Notification models in reports and utils apps.
    
    The issue is that there are two Notification models:
    1. reports.Notification - has related_application field
    2. utils.Notification - doesn't have related_application field
    
    This causes an error when trying to delete a client because the query tries to
    filter on notifications.related_application_id which doesn't exist in the utils model.
    """
    print("Starting notification models conflict fix...")
    
    # Check which table is actually being used for notifications
    with connection.cursor() as cursor:
        # Check if notifications table exists
        cursor.execute("""
            SELECT COUNT(*) 
            FROM information_schema.tables 
            WHERE table_name='notifications';
        """)
        notifications_table_exists = cursor.fetchone()[0] > 0
        
        # Check if utils_notification table exists
        cursor.execute("""
            SELECT COUNT(*) 
            FROM information_schema.tables 
            WHERE table_name='utils_notification';
        """)
        utils_notification_table_exists = cursor.fetchone()[0] > 0
    
    print(f"Table 'notifications' exists: {notifications_table_exists}")
    print(f"Table 'utils_notification' exists: {utils_notification_table_exists}")
    
    # Fix for the notifications table (reports.Notification)
    if notifications_table_exists:
        with connection.cursor() as cursor:
            # Check if related_application_id column exists
            cursor.execute("""
                SELECT COUNT(*) 
                FROM information_schema.columns 
                WHERE table_name='notifications' 
                AND column_name='related_application_id';
            """)
            column_exists = cursor.fetchone()[0] > 0
            
            if not column_exists:
                print("Adding 'related_application_id' column to 'notifications' table...")
                cursor.execute("""
                    ALTER TABLE notifications 
                    ADD COLUMN related_application_id CHAR(32) NULL;
                """)
                print("Column added successfully.")
            else:
                print("Column 'related_application_id' already exists in 'notifications' table.")
    
    # Fix for the utils_notification table
    if utils_notification_table_exists:
        with connection.cursor() as cursor:
            # Check if related_application_id column exists
            cursor.execute("""
                SELECT COUNT(*) 
                FROM information_schema.columns 
                WHERE table_name='utils_notification' 
                AND column_name='related_application_id';
            """)
            column_exists = cursor.fetchone()[0] > 0
            
            if not column_exists:
                print("Adding 'related_application_id' column to 'utils_notification' table...")
                cursor.execute("""
                    ALTER TABLE utils_notification 
                    ADD COLUMN related_application_id CHAR(32) NULL;
                """)
                print("Column added successfully.")
            else:
                print("Column 'related_application_id' already exists in 'utils_notification' table.")
    
    # Update the utils.Notification model to include the related_application field
    try:
        from utils.models import Notification as UtilsNotification
        from django.db.models.fields.related import ForeignKey
        from loans.models import LoanApplication
        
        # Check if the field already exists in the model
        if not hasattr(UtilsNotification, 'related_application'):
            print("Adding 'related_application' field to utils.Notification model...")
            # This is a runtime addition of the field, it won't persist across server restarts
            # but will help with the current session
            field = ForeignKey(LoanApplication, on_delete=django.db.models.deletion.CASCADE, null=True, blank=True)
            field.contribute_to_class(UtilsNotification, 'related_application')
            print("Field added to model successfully.")
        else:
            print("Field 'related_application' already exists in utils.Notification model.")
    except ImportError as e:
        print(f"Warning: Could not update utils.Notification model: {e}")
    
    print("\nNotification models conflict fix completed.")
    print("\nIMPORTANT: This fix adds the missing column to the database tables, but you should")
    print("update the utils/models.py file to permanently add the related_application field")
    print("to the Notification model to prevent this issue from recurring after a server restart.")
    print("\nAdd this line to utils/models.py in the Notification model:")
    print("related_application = models.ForeignKey('loans.LoanApplication', on_delete=models.CASCADE, null=True, blank=True)")

def update_utils_notification_model():
    """
    Create a migration file to update the utils.Notification model
    """
    print("\nCreating migration file to update utils.Notification model...")
    
    migration_content = """# Generated manually to fix notification model conflict

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

    dependencies = [
        ('loans', '0006_merge_20250822_2013'),
        ('utils', '0005_alter_receipt_payment_method'),
    ]

    operations = [
        migrations.AddField(
            model_name='notification',
            name='related_application',
            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='loans.loanapplication'),
        ),
    ]
"""
    
    # Create the migrations directory if it doesn't exist
    migrations_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'utils', 'migrations')
    os.makedirs(migrations_dir, exist_ok=True)
    
    # Find the next migration number
    migration_files = [f for f in os.listdir(migrations_dir) if f.endswith('.py') and f != '__init__.py']
    next_number = 6  # Default to 6 based on the last migration we saw
    
    for file in migration_files:
        if file.startswith('0'):
            try:
                number = int(file.split('_')[0][1:])
                if number >= next_number:
                    next_number = number + 1
            except ValueError:
                pass
    
    # Create the migration file
    migration_file = os.path.join(migrations_dir, f'0{next_number}_add_related_application_to_notification.py')
    with open(migration_file, 'w') as f:
        f.write(migration_content)
    
    print(f"Migration file created: {migration_file}")
    print("Run 'python manage.py migrate utils' to apply the migration.")

def update_utils_model_file():
    """
    Update the utils/models.py file to add the related_application field
    """
    print("\nUpdating utils/models.py file...")
    
    utils_models_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'utils', 'models.py')
    
    if not os.path.exists(utils_models_path):
        print(f"Error: Could not find utils/models.py at {utils_models_path}")
        return
    
    # Read the current file content
    with open(utils_models_path, 'r') as f:
        content = f.read()
    
    # Check if the field already exists
    if "related_application = models.ForeignKey('loans.LoanApplication'" in content:
        print("Field 'related_application' already exists in the file.")
        return
    
    # Find the Notification model class
    notification_class_start = content.find("class Notification(models.Model):")
    if notification_class_start == -1:
        print("Error: Could not find Notification model in utils/models.py")
        return
    
    # Find a good place to insert the field
    # Look for the end of the fields section, before the Meta class
    meta_class_start = content.find("class Meta:", notification_class_start)
    if meta_class_start == -1:
        # If Meta class not found, look for the first method
        method_start = content.find("def ", notification_class_start)
        if method_start == -1:
            # If no method found, insert at the end of the file
            insert_position = len(content)
        else:
            insert_position = method_start
    else:
        insert_position = meta_class_start
    
    # Find the last field before the insert position
    last_field_end = content.rfind("\n", notification_class_start, insert_position)
    if last_field_end == -1:
        print("Error: Could not find a good place to insert the field")
        return
    
    # Insert the new field
    new_content = content[:last_field_end + 1]
    new_content += "    related_application = models.ForeignKey('loans.LoanApplication', on_delete=models.CASCADE, null=True, blank=True)\n"
    new_content += content[last_field_end + 1:]
    
    # Create a backup of the original file
    backup_path = utils_models_path + '.bak'
    with open(backup_path, 'w') as f:
        f.write(content)
    print(f"Backup created: {backup_path}")
    
    # Write the updated content
    with open(utils_models_path, 'w') as f:
        f.write(new_content)
    
    print("utils/models.py updated successfully.")

if __name__ == "__main__":
    fix_notification_models_conflict()
    update_utils_notification_model()
    update_utils_model_file()
    print("\nAll fixes completed. Please restart your Django server.")