#!/usr/bin/env python3
"""
Complete Database Fix Script

This script fixes both the user_permissions table structure and resolves
Django migration conflicts in one comprehensive solution.

Usage:
    python complete_database_fix.py [--dry-run]
"""

import os
import sys
import subprocess
import logging
import argparse
from datetime import datetime
from pathlib import Path

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('complete_database_fix.log'),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)

class CompleteDatabaseFixer:
    """Complete database fixer for user permissions and migrations"""
    
    def __init__(self, dry_run=False):
        self.dry_run = dry_run
        self.fix_log = []
        self.start_time = datetime.now()
    
    def setup_django(self):
        """Setup Django environment"""
        try:
            import django
            os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
            django.setup()
            logger.info("Django environment setup successful")
            return True
        except Exception as e:
            logger.error(f"Django setup failed: {str(e)}")
            return False
    
    def run_command(self, command, description):
        """Run a command and log the result"""
        logger.info(f"Running: {description}")
        logger.info(f"Command: {' '.join(command)}")
        
        if self.dry_run:
            logger.info(f"[DRY RUN] Would run: {' '.join(command)}")
            self.fix_log.append(f"{description}: Would be run")
            return True
        
        try:
            result = subprocess.run(
                command,
                capture_output=True,
                text=True,
                cwd=Path.cwd()
            )
            
            if result.returncode == 0:
                logger.info(f"[SUCCESS] {description}")
                if result.stdout:
                    logger.info(f"Output: {result.stdout}")
                self.fix_log.append(f"{description}: Success")
                return True
            else:
                logger.error(f"[FAILED] {description}")
                if result.stderr:
                    logger.error(f"Error: {result.stderr}")
                if result.stdout:
                    logger.info(f"Output: {result.stdout}")
                self.fix_log.append(f"{description}: Failed")
                return False
                
        except Exception as e:
            logger.error(f"Error running command: {str(e)}")
            self.fix_log.append(f"{description}: Error")
            return False
    
    def check_database_connection(self):
        """Check database connection"""
        try:
            from django.db import connection
            with connection.cursor() as cursor:
                cursor.execute("SELECT 1")
                result = cursor.fetchone()
                if result:
                    logger.info("Database connection successful")
                    return True
        except Exception as e:
            logger.error(f"Database connection failed: {str(e)}")
            return False
        return False
    
    def get_table_structure(self, table_name):
        """Get table structure"""
        try:
            from django.db import connection
            with connection.cursor() as cursor:
                cursor.execute(f"DESCRIBE {table_name}")
                columns = cursor.fetchall()
                return columns
        except Exception as e:
            logger.error(f"Error getting table structure: {str(e)}")
            return []
    
    def fix_user_permissions_table(self):
        """Fix the user_permissions table structure"""
        logger.info("Fixing user_permissions table structure...")
        
        try:
            from django.db import connection
            
            # Check if table exists
            with connection.cursor() as cursor:
                cursor.execute("SHOW TABLES LIKE 'user_permissions'")
                table_exists = cursor.fetchone()
                
                if not table_exists:
                    logger.info("user_permissions table does not exist, will be created by migrations")
                    self.fix_log.append("user_permissions table: Will be created by migrations")
                    return True
                
                # Get current structure
                columns = self.get_table_structure('user_permissions')
                column_names = [col[0] for col in columns]
                
                # Check what needs to be fixed
                needs_fix = False
                
                # Check if module column exists and has correct type
                module_column = None
                for col in columns:
                    if col[0] == 'module':
                        module_column = col
                        break
                
                if not module_column:
                    logger.info("Module column missing, will be added by migrations")
                    needs_fix = True
                elif 'varchar(20)' in module_column[1].lower():
                    logger.info("Module column has incorrect length, will be fixed by migrations")
                    needs_fix = True
                
                # Check other required columns
                required_columns = ['action', 'is_allowed', 'granted_by_id', 'reason', 'expires_at', 'created_at', 'updated_at']
                for col in required_columns:
                    if col not in column_names:
                        logger.info(f"Column {col} missing, will be added by migrations")
                        needs_fix = True
                
                if not needs_fix:
                    logger.info("user_permissions table structure is correct")
                    self.fix_log.append("user_permissions table: Structure is correct")
                    return True
                else:
                    logger.info("user_permissions table needs fixes, will be handled by migrations")
                    self.fix_log.append("user_permissions table: Needs fixes via migrations")
                    return True
                    
        except Exception as e:
            logger.error(f"Error checking user_permissions table: {str(e)}")
            return False
    
    def fix_migration_conflicts(self):
        """Fix Django migration conflicts"""
        logger.info("Fixing Django migration conflicts...")
        
        # Step 1: Check migration status
        if not self.run_command(['python', 'manage.py', 'showmigrations', 'users'], "Check migration status"):
            logger.warning("Could not check migration status, continuing...")
        
        # Step 2: Merge conflicting migrations
        if not self.run_command(['python', 'manage.py', 'makemigrations', '--merge', 'users'], "Merge conflicting migrations"):
            logger.warning("No migrations to merge or merge failed, continuing...")
        
        # Step 3: Create any missing migrations
        if not self.run_command(['python', 'manage.py', 'makemigrations', 'users'], "Create missing migrations"):
            logger.info("No new migrations needed")
        
        # Step 4: Apply migrations
        if not self.run_command(['python', 'manage.py', 'migrate', 'users'], "Apply migrations"):
            logger.error("Failed to apply migrations")
            return False
        
        return True
    
    def verify_fix(self):
        """Verify that the fix worked"""
        logger.info("Verifying the fix...")
        
        if self.dry_run:
            logger.info("[DRY RUN] Would verify fix")
            self.fix_log.append("Verification: Would be run")
            return True
        
        try:
            from django.db import connection
            with connection.cursor() as cursor:
                # Try to query the table with the module column
                cursor.execute("SELECT COUNT(*) FROM user_permissions WHERE module = 'test'")
                result = cursor.fetchone()
                logger.info("[SUCCESS] user_permissions table is working correctly")
                self.fix_log.append("Verification: Passed")
                return True
        except Exception as e:
            logger.error(f"[FAILED] Verification failed: {str(e)}")
            self.fix_log.append("Verification: Failed")
            return False
    
    def fix(self):
        """Main fix method"""
        logger.info("=" * 80)
        logger.info("COMPLETE DATABASE FIX: USER PERMISSIONS & MIGRATIONS")
        logger.info("=" * 80)
        logger.info(f"Dry run: {self.dry_run}")
        logger.info(f"Start time: {self.start_time}")
        logger.info("=" * 80)
        
        try:
            # Setup Django
            if not self.setup_django():
                return False
            
            # Check database connection
            if not self.check_database_connection():
                return False
            
            # Fix user_permissions table
            if not self.fix_user_permissions_table():
                return False
            
            # Fix migration conflicts
            if not self.fix_migration_conflicts():
                return False
            
            # Verify fix
            if not self.verify_fix():
                return False
            
            # Calculate fix time
            end_time = datetime.now()
            fix_time = end_time - self.start_time
            
            # Log summary
            logger.info("=" * 80)
            logger.info("FIX SUMMARY")
            logger.info("=" * 80)
            for log_entry in self.fix_log:
                logger.info(f"  {log_entry}")
            logger.info("=" * 80)
            logger.info(f"Fix time: {fix_time}")
            logger.info(f"End time: {end_time}")
            
            if self.dry_run:
                logger.info("DRY RUN COMPLETED - No changes were made")
            else:
                logger.info("COMPLETE DATABASE FIX COMPLETED SUCCESSFULLY!")
                logger.info("The user_permissions table and migrations should now work correctly.")
            
            return True
            
        except Exception as e:
            logger.error(f"Complete database fix failed: {str(e)}")
            return False

def main():
    """Main function with argument parsing"""
    parser = argparse.ArgumentParser(
        description='Complete database fix for user permissions and migrations',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
Examples:
  python complete_database_fix.py                    # Fix everything
  python complete_database_fix.py --dry-run          # Test fix
        '''
    )
    
    parser.add_argument('--dry-run', action='store_true',
                       help='Show what would be done without making changes')
    
    args = parser.parse_args()
    
    try:
        fixer = CompleteDatabaseFixer(dry_run=args.dry_run)
        success = fixer.fix()
        sys.exit(0 if success else 1)
        
    except Exception as e:
        logger.error(f"Script failed: {str(e)}")
        sys.exit(1)

if __name__ == '__main__':
    main()
