"""
Production 500 Error Investigation Script
Diagnoses common causes of Internal Server Errors
"""
import os
import sys
import django
from pathlib import Path

# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'branch_system.settings')
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

try:
    django.setup()
except Exception as e:
    print(f"❌ CRITICAL: Django setup failed: {e}")
    print("\nThis is likely your 500 error cause!")
    sys.exit(1)

from django.conf import settings
from django.db import connection, connections
from django.core.management import call_command
import traceback

def print_section(title):
    print(f"\n{'='*60}")
    print(f"  {title}")
    print('='*60)

def check_database_connection():
    """Check if database is accessible"""
    print_section("DATABASE CONNECTION")
    try:
        with connection.cursor() as cursor:
            cursor.execute("SELECT 1")
            print("✅ Database connection: OK")
            
            # Check database name
            cursor.execute("SELECT DATABASE()")
            db_name = cursor.fetchone()[0]
            print(f"✅ Connected to database: {db_name}")
            
            return True
    except Exception as e:
        print(f"❌ Database connection FAILED: {e}")
        print("\n🔍 Possible causes:")
        print("  - Wrong database credentials in settings")
        print("  - Database server is down")
        print("  - Network/firewall issues")
        print("  - Database doesn't exist")
        return False

def check_required_tables():
    """Check if critical tables exist"""
    print_section("REQUIRED TABLES")
    
    required_tables = [
        'django_session',
        'django_content_type',
        'auth_permission',
        'users_customuser',
        'loans_loan',
        'loans_client',
    ]
    
    try:
        with connection.cursor() as cursor:
            cursor.execute("SHOW TABLES")
            existing_tables = [table[0] for table in cursor.fetchall()]
            
            missing_tables = []
            for table in required_tables:
                if table in existing_tables:
                    print(f"✅ {table}")
                else:
                    print(f"❌ {table} - MISSING")
                    missing_tables.append(table)
            
            if missing_tables:
                print(f"\n⚠️  Missing {len(missing_tables)} critical tables!")
                print("Run: python manage.py migrate")
                return False
            
            return True
    except Exception as e:
        print(f"❌ Could not check tables: {e}")
        return False

def check_migrations():
    """Check for unapplied migrations"""
    print_section("MIGRATIONS STATUS")
    try:
        from django.db.migrations.executor import MigrationExecutor
        
        executor = MigrationExecutor(connection)
        plan = executor.migration_plan(executor.loader.graph.leaf_nodes())
        
        if plan:
            print(f"⚠️  {len(plan)} unapplied migrations found:")
            for migration, backwards in plan[:10]:  # Show first 10
                print(f"  - {migration.app_label}.{migration.name}")
            
            if len(plan) > 10:
                print(f"  ... and {len(plan) - 10} more")
            
            print("\n🔧 Fix: python manage.py migrate")
            return False
        else:
            print("✅ All migrations applied")
            return True
    except Exception as e:
        print(f"❌ Could not check migrations: {e}")
        return False

def check_static_files():
    """Check static files configuration"""
    print_section("STATIC FILES")
    
    print(f"STATIC_URL: {settings.STATIC_URL}")
    print(f"STATIC_ROOT: {getattr(settings, 'STATIC_ROOT', 'Not set')}")
    
    static_root = getattr(settings, 'STATIC_ROOT', None)
    if static_root:
        static_path = Path(static_root)
        if static_path.exists():
            file_count = len(list(static_path.rglob('*')))
            print(f"✅ STATIC_ROOT exists with {file_count} files")
        else:
            print(f"⚠️  STATIC_ROOT directory doesn't exist")
            print("Run: python manage.py collectstatic")
    else:
        print("⚠️  STATIC_ROOT not configured")

def check_media_files():
    """Check media files configuration"""
    print_section("MEDIA FILES")
    
    print(f"MEDIA_URL: {settings.MEDIA_URL}")
    print(f"MEDIA_ROOT: {getattr(settings, 'MEDIA_ROOT', 'Not set')}")
    
    media_root = getattr(settings, 'MEDIA_ROOT', None)
    if media_root:
        media_path = Path(media_root)
        if media_path.exists():
            print(f"✅ MEDIA_ROOT exists")
        else:
            print(f"⚠️  MEDIA_ROOT directory doesn't exist")
            print(f"Creating: {media_root}")
            media_path.mkdir(parents=True, exist_ok=True)
    else:
        print("⚠️  MEDIA_ROOT not configured")

def check_environment_variables():
    """Check critical environment variables"""
    print_section("ENVIRONMENT VARIABLES")
    
    critical_vars = [
        'SECRET_KEY',
        'DEBUG',
        'ALLOWED_HOSTS',
        'DATABASE_NAME',
        'DATABASE_USER',
        'DATABASE_PASSWORD',
        'DATABASE_HOST',
    ]
    
    for var in critical_vars:
        value = os.getenv(var)
        if value:
            if 'PASSWORD' in var or 'SECRET' in var:
                print(f"✅ {var}: ***hidden***")
            else:
                print(f"✅ {var}: {value}")
        else:
            # Check if it's in settings
            setting_value = getattr(settings, var, None)
            if setting_value:
                if 'PASSWORD' in var or 'SECRET' in var:
                    print(f"✅ {var}: ***hidden*** (from settings)")
                else:
                    print(f"✅ {var}: {setting_value} (from settings)")
            else:
                print(f"⚠️  {var}: Not set")

def check_debug_mode():
    """Check DEBUG setting"""
    print_section("DEBUG MODE")
    
    if settings.DEBUG:
        print("⚠️  DEBUG = True")
        print("This should be False in production!")
    else:
        print("✅ DEBUG = False (production mode)")

def check_allowed_hosts():
    """Check ALLOWED_HOSTS configuration"""
    print_section("ALLOWED HOSTS")
    
    allowed_hosts = settings.ALLOWED_HOSTS
    print(f"ALLOWED_HOSTS: {allowed_hosts}")
    
    if not allowed_hosts or allowed_hosts == []:
        print("❌ ALLOWED_HOSTS is empty!")
        print("Add your domain to ALLOWED_HOSTS")
        return False
    elif '*' in allowed_hosts:
        print("⚠️  Using wildcard '*' - not recommended for production")
    else:
        print(f"✅ {len(allowed_hosts)} host(s) configured")
    
    return True

def check_installed_apps():
    """Check if all installed apps are valid"""
    print_section("INSTALLED APPS")
    
    try:
        from django.apps import apps
        app_configs = apps.get_app_configs()
        print(f"✅ {len(app_configs)} apps loaded successfully")
        
        # List custom apps
        custom_apps = [app.name for app in app_configs 
                      if not app.name.startswith('django.')]
        print(f"\nCustom apps: {', '.join(custom_apps)}")
        return True
    except Exception as e:
        print(f"❌ Error loading apps: {e}")
        traceback.print_exc()
        return False

def check_middleware():
    """Check middleware configuration"""
    print_section("MIDDLEWARE")
    
    try:
        middleware = settings.MIDDLEWARE
        print(f"✅ {len(middleware)} middleware classes configured")
        
        # Check for common required middleware
        required = [
            'django.middleware.security.SecurityMiddleware',
            'django.contrib.sessions.middleware.SessionMiddleware',
            'django.middleware.common.CommonMiddleware',
            'django.contrib.auth.middleware.AuthenticationMiddleware',
        ]
        
        for mw in required:
            if mw in middleware:
                print(f"  ✅ {mw.split('.')[-1]}")
            else:
                print(f"  ⚠️  {mw.split('.')[-1]} - missing")
        
        return True
    except Exception as e:
        print(f"❌ Middleware check failed: {e}")
        return False

def check_templates():
    """Check template configuration"""
    print_section("TEMPLATES")
    
    try:
        templates = settings.TEMPLATES
        if templates:
            print(f"✅ {len(templates)} template engine(s) configured")
            
            for template in templates:
                backend = template.get('BACKEND', '').split('.')[-1]
                dirs = template.get('DIRS', [])
                print(f"\n  Backend: {backend}")
                print(f"  Template dirs: {len(dirs)}")
                
                for dir_path in dirs:
                    if Path(dir_path).exists():
                        print(f"    ✅ {dir_path}")
                    else:
                        print(f"    ⚠️  {dir_path} - doesn't exist")
        
        return True
    except Exception as e:
        print(f"❌ Template check failed: {e}")
        return False

def check_logs():
    """Check for recent error logs"""
    print_section("ERROR LOGS")
    
    log_locations = [
        'logs/error.log',
        'logs/django.log',
        'error.log',
        'django.log',
        '/var/log/apache2/error.log',
        '/var/log/httpd/error_log',
    ]
    
    found_logs = False
    for log_path in log_locations:
        if os.path.exists(log_path):
            found_logs = True
            print(f"\n📄 Found log: {log_path}")
            try:
                with open(log_path, 'r', encoding='utf-8', errors='ignore') as f:
                    lines = f.readlines()
                    recent_lines = lines[-50:]  # Last 50 lines
                    
                    # Look for errors
                    errors = [line for line in recent_lines 
                             if 'error' in line.lower() or 'exception' in line.lower()]
                    
                    if errors:
                        print(f"  Found {len(errors)} recent error(s):")
                        for error in errors[-5:]:  # Show last 5
                            print(f"    {error.strip()[:100]}")
                    else:
                        print("  No recent errors found")
            except Exception as e:
                print(f"  Could not read log: {e}")
    
    if not found_logs:
        print("⚠️  No log files found")
        print("\nCheck your web server logs:")
        print("  - Apache: /var/log/apache2/error.log")
        print("  - Nginx: /var/log/nginx/error.log")
        print("  - cPanel: ~/logs/")

def check_database_tables_structure():
    """Check for common table structure issues"""
    print_section("DATABASE STRUCTURE")
    
    try:
        with connection.cursor() as cursor:
            # Check users_customuser table
            cursor.execute("""
                SELECT COUNT(*) 
                FROM information_schema.COLUMNS 
                WHERE TABLE_SCHEMA = DATABASE() 
                AND TABLE_NAME = 'users_customuser'
            """)
            user_columns = cursor.fetchone()[0]
            
            if user_columns > 0:
                print(f"✅ users_customuser has {user_columns} columns")
            else:
                print("❌ users_customuser table missing or empty")
                return False
            
            # Check for common issues
            cursor.execute("""
                SELECT TABLE_NAME, TABLE_COLLATION
                FROM information_schema.TABLES
                WHERE TABLE_SCHEMA = DATABASE()
                AND TABLE_TYPE = 'BASE TABLE'
                LIMIT 5
            """)
            
            tables = cursor.fetchall()
            print(f"\nSample table collations:")
            for table_name, collation in tables:
                print(f"  {table_name}: {collation}")
            
        return True
    except Exception as e:
        print(f"❌ Structure check failed: {e}")
        return False

def main():
    print("\n" + "="*60)
    print("  🔍 PRODUCTION 500 ERROR INVESTIGATION")
    print("="*60)
    
    issues_found = []
    
    # Run all checks
    checks = [
        ("Database Connection", check_database_connection),
        ("Required Tables", check_required_tables),
        ("Migrations", check_migrations),
        ("Debug Mode", check_debug_mode),
        ("Allowed Hosts", check_allowed_hosts),
        ("Installed Apps", check_installed_apps),
        ("Middleware", check_middleware),
        ("Templates", check_templates),
        ("Static Files", check_static_files),
        ("Media Files", check_media_files),
        ("Environment Variables", check_environment_variables),
        ("Database Structure", check_database_tables_structure),
    ]
    
    for check_name, check_func in checks:
        try:
            result = check_func()
            if result is False:
                issues_found.append(check_name)
        except Exception as e:
            print(f"\n❌ {check_name} check crashed: {e}")
            traceback.print_exc()
            issues_found.append(check_name)
    
    # Check logs last
    check_logs()
    
    # Summary
    print_section("SUMMARY")
    
    if issues_found:
        print(f"❌ Found {len(issues_found)} issue(s):")
        for issue in issues_found:
            print(f"  - {issue}")
        
        print("\n🔧 RECOMMENDED ACTIONS:")
        print("1. Check the error logs above for specific error messages")
        print("2. Fix any database connection issues first")
        print("3. Run: python manage.py migrate")
        print("4. Run: python manage.py collectstatic")
        print("5. Ensure ALLOWED_HOSTS includes your domain")
        print("6. Check web server error logs (Apache/Nginx)")
        print("7. Restart your web server/application")
    else:
        print("✅ No obvious issues found!")
        print("\n🔍 Additional debugging steps:")
        print("1. Check web server error logs")
        print("2. Enable DEBUG=True temporarily to see detailed error")
        print("3. Check file permissions (media, static, logs)")
        print("4. Verify Python packages: pip install -r requirements.txt")
        print("5. Check for syntax errors in recent code changes")

if __name__ == '__main__':
    main()
