# Generated manually for performance optimization

from typing import Any, List, Tuple, Optional
from django.db import migrations, connection


def create_indexes(apps: Any, schema_editor: Any) -> None:
    """
    Create performance indexes for both PostgreSQL and MySQL compatibility.
    Uses CONCURRENTLY for PostgreSQL production, regular CREATE INDEX for tests/transactions.
    """
    db_engine = connection.vendor

    indexes: List[Tuple[str, str, str, Optional[str]]] = [
        # ConfirmedEmail indexes
        ("idx_cemail_digest", "ivataraccount_confirmedemail", "digest", None),
        (
            "idx_cemail_digest_sha256",
            "ivataraccount_confirmedemail",
            "digest_sha256",
            None,
        ),
        (
            "idx_cemail_access_count",
            "ivataraccount_confirmedemail",
            "access_count",
            None,
        ),
        (
            "idx_cemail_bluesky_handle",
            "ivataraccount_confirmedemail",
            "bluesky_handle",
            "WHERE bluesky_handle IS NOT NULL",
        ),
        # Photo indexes
        ("idx_photo_format", "ivataraccount_photo", "format", None),
        ("idx_photo_access_count", "ivataraccount_photo", "access_count", None),
        # Composite indexes
        (
            "idx_cemail_user_access",
            "ivataraccount_confirmedemail",
            "user_id, access_count",
            None,
        ),
        (
            "idx_cemail_photo_access",
            "ivataraccount_confirmedemail",
            "photo_id, access_count",
            None,
        ),
        ("idx_photo_user_format", "ivataraccount_photo", "user_id, format", None),
    ]

    with connection.cursor() as cursor:
        # Check if we're in a transaction (test environment)
        try:
            cursor.execute("SELECT 1")
            in_transaction = connection.in_atomic_block
        except Exception:
            in_transaction = True

        for index_name, table_name, columns, where_clause in indexes:
            try:
                if db_engine == "postgresql":
                    # Use CONCURRENTLY only if not in a transaction (production)
                    # Use regular CREATE INDEX if in a transaction (tests)
                    if in_transaction:
                        # In transaction (test environment) - use regular CREATE INDEX
                        if where_clause:
                            sql = f"CREATE INDEX IF NOT EXISTS {index_name} ON {table_name}({columns}) {where_clause};"
                        else:
                            sql = f"CREATE INDEX IF NOT EXISTS {index_name} ON {table_name}({columns});"
                    else:
                        # Not in transaction (production) - use CONCURRENTLY
                        if where_clause:
                            sql = f"CREATE INDEX CONCURRENTLY IF NOT EXISTS {index_name} ON {table_name}({columns}) {where_clause};"
                        else:
                            sql = f"CREATE INDEX CONCURRENTLY IF NOT EXISTS {index_name} ON {table_name}({columns});"
                else:
                    # MySQL and other databases - skip partial indexes
                    if where_clause:
                        print(
                            f"Skipping partial index {index_name} for {db_engine} (not supported)"
                        )
                        continue
                    sql = f"CREATE INDEX IF NOT EXISTS {index_name} ON {table_name}({columns});"

                cursor.execute(sql)
                print(f"Created index: {index_name}")

            except Exception as e:
                # Index might already exist or other error - log and continue
                print(f"Index {index_name} creation skipped: {e}")


def drop_indexes(apps: Any, schema_editor: Any) -> None:
    """
    Drop the performance indexes.
    """
    indexes: List[str] = [
        "idx_cemail_digest",
        "idx_cemail_digest_sha256",
        "idx_cemail_access_count",
        "idx_cemail_bluesky_handle",
        "idx_photo_format",
        "idx_photo_access_count",
        "idx_cemail_user_access",
        "idx_cemail_photo_access",
        "idx_photo_user_format",
    ]

    with connection.cursor() as cursor:
        for index_name in indexes:
            try:
                cursor.execute(f"DROP INDEX IF EXISTS {index_name};")
                print(f"Dropped index: {index_name}")
            except Exception as e:
                print(f"Index {index_name} drop skipped: {e}")


class Migration(migrations.Migration):

    dependencies = [
        ("ivataraccount", "0020_confirmedopenid_bluesky_handle"),
    ]

    operations = [
        migrations.RunPython(create_indexes, drop_indexes),
    ]
