# Generated migration for Phase 2 - GIN Index Optimization
from django.db import migrations, connection
from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import SearchVector


def is_postgresql():
    """Check if the database backend is PostgreSQL/PostGIS."""
    return 'postgis' in connection.vendor or 'postgresql' in connection.vendor


def populate_search_vectors(apps, schema_editor):
    """Populate search_vector fields for all existing records."""
    if not is_postgresql():
        return
    
    # Get models
    Company = apps.get_model('entities', 'Company')
    RideModel = apps.get_model('entities', 'RideModel')
    Park = apps.get_model('entities', 'Park')
    Ride = apps.get_model('entities', 'Ride')
    
    # Update Company search vectors
    Company.objects.update(
        search_vector=(
            SearchVector('name', weight='A') + 
            SearchVector('description', weight='B')
        )
    )
    
    # Update RideModel search vectors
    RideModel.objects.update(
        search_vector=(
            SearchVector('name', weight='A') +
            SearchVector('manufacturer__name', weight='A') +
            SearchVector('description', weight='B')
        )
    )
    
    # Update Park search vectors
    Park.objects.update(
        search_vector=(
            SearchVector('name', weight='A') +
            SearchVector('description', weight='B')
        )
    )
    
    # Update Ride search vectors
    Ride.objects.update(
        search_vector=(
            SearchVector('name', weight='A') +
            SearchVector('park__name', weight='A') +
            SearchVector('manufacturer__name', weight='B') +
            SearchVector('description', weight='B')
        )
    )


def reverse_search_vectors(apps, schema_editor):
    """Clear search_vector fields for all records."""
    if not is_postgresql():
        return
    
    # Get models
    Company = apps.get_model('entities', 'Company')
    RideModel = apps.get_model('entities', 'RideModel')
    Park = apps.get_model('entities', 'Park')
    Ride = apps.get_model('entities', 'Ride')
    
    # Clear all search vectors
    Company.objects.update(search_vector=None)
    RideModel.objects.update(search_vector=None)
    Park.objects.update(search_vector=None)
    Ride.objects.update(search_vector=None)


def add_gin_indexes(apps, schema_editor):
    """Add GIN indexes on search_vector fields (PostgreSQL only)."""
    if not is_postgresql():
        return
    
    # Use raw SQL to add GIN indexes
    with schema_editor.connection.cursor() as cursor:
        cursor.execute("""
            CREATE INDEX IF NOT EXISTS entities_company_search_idx 
            ON entities_company USING gin(search_vector);
        """)
        cursor.execute("""
            CREATE INDEX IF NOT EXISTS entities_ridemodel_search_idx 
            ON entities_ridemodel USING gin(search_vector);
        """)
        cursor.execute("""
            CREATE INDEX IF NOT EXISTS entities_park_search_idx 
            ON entities_park USING gin(search_vector);
        """)
        cursor.execute("""
            CREATE INDEX IF NOT EXISTS entities_ride_search_idx 
            ON entities_ride USING gin(search_vector);
        """)


def remove_gin_indexes(apps, schema_editor):
    """Remove GIN indexes (PostgreSQL only)."""
    if not is_postgresql():
        return
    
    # Use raw SQL to drop GIN indexes
    with schema_editor.connection.cursor() as cursor:
        cursor.execute("DROP INDEX IF EXISTS entities_company_search_idx;")
        cursor.execute("DROP INDEX IF EXISTS entities_ridemodel_search_idx;")
        cursor.execute("DROP INDEX IF EXISTS entities_park_search_idx;")
        cursor.execute("DROP INDEX IF EXISTS entities_ride_search_idx;")


class Migration(migrations.Migration):
    """
    Phase 2 Migration: Add GIN indexes for search optimization.
    
    This migration:
    1. Adds GIN indexes on search_vector fields for optimal full-text search
    2. Populates search vectors for all existing database records
    3. Is PostgreSQL-specific and safe for SQLite environments
    """
    
    dependencies = [
        ('entities', '0002_alter_park_latitude_alter_park_longitude'),
    ]
    
    operations = [
        # First, populate search vectors for existing records
        migrations.RunPython(
            populate_search_vectors,
            reverse_search_vectors,
        ),
        
        # Add GIN indexes for each model's search_vector field
        migrations.RunPython(
            add_gin_indexes,
            remove_gin_indexes,
        ),
    ]
