#!/usr/bin/env python
"""
Comprehensive M-Pesa Payment Fix Deployment Script for cPanel Production
This script handles:
1. Creating migrations for payments, loans, and utils apps
2. Applying migrations
3. Fixing utils_notification table (action_required column)
4. Verifying all changes
Run this in production to deploy all M-Pesa payment fixes
"""
import os
import sys
import django
from pathlib import Path

# Auto-detect Django settings
def setup_django():
    """Setup Django environment"""
    script_dir = Path(__file__).resolve().parent
    
    # Try to find manage.py
    manage_py = script_dir / 'manage.py'
    if not manage_py.exists():
        # Try parent directory
        manage_py = script_dir.parent / 'manage.py'
    
    if manage_py.exists():
        # Read manage.py to find settings module
        with open(manage_py, 'r') as f:
            content = f.read()
            if 'DJANGO_SETTINGS_MODULE' in content:
                import re
                match = re.search(r"os\.environ\.setdefault\(['\"]DJANGO_SETTINGS_MODULE['\"],\s*['\"]([^'\"]+)['\"]", content)
                if match:
                    os.environ.setdefault('DJANGO_SETTINGS_MODULE', match.group(1))
    
    # Try common settings module names
    settings_modules = [
        'config.settings',
        'settings',
        'project.settings',
        'branchsystem.settings',
        'branch_system.settings',
    ]
    
    for settings_module in settings_modules:
        try:
            os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module)
            django.setup()
            print(f"✓ Django setup successful with settings: {settings_module}")
            return True
        except Exception as e:
            continue
    
    print("✗ Error: Could not setup Django. Please set DJANGO_SETTINGS_MODULE")
    return False

def check_migrations():
    """Check migration status"""
    from django.core.management import execute_from_command_line
    from django.core.management import call_command
    from io import StringIO
    import sys
    
    print("\n" + "="*70)
    print("STEP 1: CHECKING MIGRATION STATUS")
    print("="*70)
    
    apps = ['payments', 'loans', 'utils']
    
    for app in apps:
        print(f"\n→ Checking {app} app migrations...")
        try:
            output = StringIO()
            sys.stdout = output
            call_command('showmigrations', app, verbosity=0)
            sys.stdout = sys.__stdout__
            result = output.getvalue()
            
            unapplied = [line.strip() for line in result.split('\n') if '[ ]' in line]
            if unapplied:
                print(f"  ⚠ Unapplied migrations in {app}:")
                for migration in unapplied:
                    print(f"    - {migration}")
                return False
            else:
                print(f"  ✓ All {app} migrations are applied")
        except Exception as e:
            print(f"  ⚠ Error checking {app}: {e}")
    
    return True

def create_migrations():
    """Create migrations for payments, loans, and utils"""
    from django.core.management import call_command
    
    print("\n" + "="*70)
    print("STEP 2: CREATING MIGRATIONS")
    print("="*70)
    
    apps = ['payments', 'loans', 'utils']
    
    for app in apps:
        print(f"\n→ Creating migrations for {app}...")
        try:
            call_command('makemigrations', app, verbosity=1, interactive=False)
            print(f"  ✓ Migrations created for {app}")
        except Exception as e:
            print(f"  ⚠ Error creating migrations for {app}: {e}")
            if "No changes detected" in str(e):
                print(f"  ✓ No changes detected in {app} (this is OK)")

def apply_migrations():
    """Apply migrations"""
    from django.core.management import call_command
    
    print("\n" + "="*70)
    print("STEP 3: APPLYING MIGRATIONS")
    print("="*70)
    
    try:
        call_command('migrate', verbosity=1, interactive=False)
        print("\n✓ All migrations applied successfully")
        return True
    except Exception as e:
        print(f"\n✗ Error applying migrations: {e}")
        return False

def fix_notifications_table():
    """Fix utils_notification table - add missing columns"""
    from django.db import connection
    
    print("\n" + "="*70)
    print("STEP 4: FIXING utils_notification TABLE")
    print("="*70)
    
    try:
        with connection.cursor() as cursor:
            # Check if column exists
            cursor.execute("""
                SELECT COUNT(*) 
                FROM information_schema.COLUMNS 
                WHERE TABLE_SCHEMA = DATABASE()
                AND TABLE_NAME = 'utils_notification'
                AND COLUMN_NAME = 'action_required'
            """)
            
            exists = cursor.fetchone()[0] > 0
            
            if exists:
                print("✓ Column 'action_required' already exists")
            else:
                print("⚠ Column 'action_required' does not exist. Adding it...")
                
                # Add the column
                cursor.execute("""
                    ALTER TABLE `utils_notification` 
                    ADD COLUMN `action_required` tinyint(1) NOT NULL DEFAULT 0
                    COMMENT 'Whether this notification requires immediate action'
                """)
                
                print("✓ Column 'action_required' added successfully")
            
            # Check for other missing columns
            columns_to_check = [
                ('alert_data', 'json', 'DEFAULT NULL COMMENT \'Additional alert data in JSON format\''),
                ('portfolio_snapshot_id', 'char(32)', 'NULL'),
            ]
            
            for col_name, col_type, extra in columns_to_check:
                cursor.execute("""
                    SELECT COUNT(*) 
                    FROM information_schema.COLUMNS 
                    WHERE TABLE_SCHEMA = DATABASE()
                    AND TABLE_NAME = 'utils_notification'
                    AND COLUMN_NAME = %s
                """, [col_name])
                
                exists = cursor.fetchone()[0] > 0
                
                if exists:
                    print(f"✓ Column '{col_name}' already exists")
                else:
                    print(f"⚠ Column '{col_name}' does not exist. Adding it...")
                    cursor.execute(f"""
                        ALTER TABLE `utils_notification` 
                        ADD COLUMN `{col_name}` {col_type} {extra}
                    """)
                    print(f"✓ Column '{col_name}' added successfully")
        
        print("\n✓ utils_notification table fix completed")
        return True
        
    except Exception as e:
        print(f"\n✗ Error fixing utils_notification table: {e}")
        return False

def verify_changes():
    """Verify all changes are applied"""
    from django.db import connection
    from django.apps import apps
    
    print("\n" + "="*70)
    print("STEP 5: VERIFYING CHANGES")
    print("="*70)
    
    # Verify UnconfirmedPayment model exists
    try:
        UnconfirmedPayment = apps.get_model('payments', 'UnconfirmedPayment')
        print("✓ UnconfirmedPayment model found")
        
        # Check if table exists
        with connection.cursor() as cursor:
            cursor.execute("""
                SELECT COUNT(*) 
                FROM information_schema.TABLES 
                WHERE TABLE_SCHEMA = DATABASE()
                AND TABLE_NAME = 'unconfirmed_payments'
            """)
            exists = cursor.fetchone()[0] > 0
            
            if exists:
                print("✓ unconfirmed_payments table exists")
            else:
                print("✗ unconfirmed_payments table does not exist (migration needed)")
                return False
    except Exception as e:
        print(f"✗ Error verifying UnconfirmedPayment: {e}")
        return False
    
    # Verify MpesaTransaction has pending_approval status
    try:
        MpesaTransaction = apps.get_model('loans', 'MpesaTransaction')
        status_choices = dict(MpesaTransaction.STATUS_CHOICES)
        if 'pending_approval' in status_choices:
            print("✓ MpesaTransaction has 'pending_approval' status")
        else:
            print("⚠ MpesaTransaction does not have 'pending_approval' status")
    except Exception as e:
        print(f"⚠ Error verifying MpesaTransaction: {e}")
    
    # Verify utils_notification columns
    try:
        with connection.cursor() as cursor:
            cursor.execute("""
                SELECT COLUMN_NAME 
                FROM information_schema.COLUMNS 
                WHERE TABLE_SCHEMA = DATABASE()
                AND TABLE_NAME = 'utils_notification'
            """)
            columns = [row[0] for row in cursor.fetchall()]
            
            required_columns = ['action_required', 'alert_data', 'portfolio_snapshot_id']
            for col in required_columns:
                if col in columns:
                    print(f"✓ Column '{col}' exists in utils_notification")
                else:
                    print(f"✗ Column '{col}' missing in utils_notification")
                    return False
    except Exception as e:
        print(f"✗ Error verifying utils_notification columns: {e}")
        return False
    
    print("\n✓ All verifications passed")
    return True

def create_missing_templates():
    """Create missing templates if they don't exist"""
    import os
    from pathlib import Path
    
    print("\n" + "="*70)
    print("STEP 6: CHECKING TEMPLATES")
    print("="*70)
    
    script_dir = Path(__file__).resolve().parent
    templates_dir = script_dir / 'templates' / 'payments'
    
    if not templates_dir.exists():
        print(f"⚠ Templates directory not found: {templates_dir}")
        print("  Please ensure templates are uploaded manually via cPanel File Manager")
        return
    
    required_templates = [
        'unconfirmed_payments.html',
        'unconfirmed_payment_detail.html',
    ]
    
    missing = []
    for template in required_templates:
        template_path = templates_dir / template
        if template_path.exists():
            print(f"✓ Template exists: {template}")
        else:
            print(f"✗ Template missing: {template}")
            missing.append(template)
    
    if missing:
        print(f"\n⚠ Missing templates: {', '.join(missing)}")
        print("  These need to be created manually or uploaded via cPanel")
    else:
        print("\n✓ All required templates are present")

def main():
    """Main deployment function"""
    print("="*70)
    print("M-PESA PAYMENT FIX - COMPREHENSIVE DEPLOYMENT SCRIPT")
    print("="*70)
    print("\nThis script will:")
    print("  1. Check migration status")
    print("  2. Create missing migrations")
    print("  3. Apply migrations")
    print("  4. Fix utils_notification table (action_required column)")
    print("  5. Verify all changes")
    print("  6. Check for missing templates")
    print("\n" + "="*70)
    
    # Setup Django
    if not setup_django():
        sys.exit(1)
    
    # Check migrations
    check_migrations()
    
    # Create migrations
    create_migrations()
    
    # Apply migrations
    if not apply_migrations():
        print("\n⚠ Migration errors occurred. Continuing with SQL fixes...")
    
    # Fix notifications table
    if not fix_notifications_table():
        print("\n⚠ SQL fix errors occurred. Please check manually.")
    
    # Verify changes
    if not verify_changes():
        print("\n⚠ Verification failed. Please check errors above.")
    
    # Check templates
    create_missing_templates()
    
    # Summary
    print("\n" + "="*70)
    print("DEPLOYMENT COMPLETED")
    print("="*70)
    print("\nNEXT STEPS:")
    print("  1. Restart your Django application in cPanel")
    print("  2. Upload missing templates via cPanel File Manager if needed")
    print("  3. Test M-Pesa payment matching at /payments/unconfirmed-payments/")
    print("  4. Check /utils/notifications/ to ensure no errors")
    print("\n" + "="*70)

if __name__ == '__main__':
    main()
