# Generated by Django 3.2.25 on 2024-07-31 16:38

from django.conf import settings
from django.db import migrations, models
from django.db.migrations.operations.special import RunSQL
from django.db.migrations.operations.base import Operation
from django.db import connection
from core.redis import start_job_async_or_sync
from core.models import AsyncMigrationStatus
import logging
logger = logging.getLogger(__name__)


IS_SQLITE = connection.vendor == 'sqlite'
migration_name = '0017_auto_20240731_1638'

def create_index_sql(table_name, index_name, column_name):
    return f"""
    CREATE INDEX CONCURRENTLY IF NOT EXISTS "{index_name}" ON "{table_name}" ("{column_name}");
    """

def create_fk_sql(table_name, constraint_name, column_name, referenced_table, referenced_column):
    return f"""
    ALTER TABLE "{table_name}" DROP CONSTRAINT IF EXISTS "{constraint_name}";
    ALTER TABLE "{table_name}" ADD CONSTRAINT "{constraint_name}" FOREIGN KEY ("{column_name}") REFERENCES "{referenced_table}" ("{referenced_column}") DEFERRABLE INITIALLY DEFERRED;
    """

def drop_index_sql(table_name, index_name, column_name):
    return f"""
    DROP INDEX CONCURRENTLY IF EXISTS "{index_name}";
    """

tables = [
    {
        "model_name": "azureblobexportstoragelink",
        "table_name": "io_storages_azureblobexportstoragelink",
        "index_name": "io_storages_azureblobexportstoragelink_annotation_id_6cc15c83",
        "fk_constraint": "io_storages_azureblo_annotation_id_6cc15c83_fk_task_comp",
        "column_name": "annotation_id"
    },
    {
        "model_name": "gcsexportstoragelink",
        "table_name": "io_storages_gcsexportstoragelink",
        "index_name": "io_storages_gcsexportstoragelink_annotation_id_2df715a6",
        "fk_constraint": "io_storages_gcsexpor_annotation_id_2df715a6_fk_task_comp",
        "column_name": "annotation_id"
    },
    {
        "model_name": "localfilesexportstoragelink",
        "table_name": "io_storages_localfilesexportstoragelink",
        "index_name": "io_storages_localfilesexportstoragelink_annotation_id_fc4f9825",
        "fk_constraint": "io_storages_localfil_annotation_id_fc4f9825_fk_task_comp",
        "column_name": "annotation_id"
    },
    {
        "model_name": "redisexportstoragelink",
        "table_name": "io_storages_redisexportstoragelink",
        "index_name": "io_storages_redisexportstoragelink_annotation_id_8547e508",
        "fk_constraint": "io_storages_redisexp_annotation_id_8547e508_fk_task_comp",
        "column_name": "annotation_id"
    },
    {
        "model_name": "s3exportstoragelink",
        "table_name": "io_storages_s3exportstoragelink",
        "index_name": "io_storages_s3exportstoragelink_annotation_id_729994fe",
        "fk_constraint": "io_storages_s3export_annotation_id_729994fe_fk_task_comp",
        "column_name": "annotation_id"
    }
]


def forward_migration(migration_name, db_alias):
    migration = AsyncMigrationStatus.objects.using(db_alias).create(
        name=migration_name,
        status=AsyncMigrationStatus.STATUS_STARTED,
    )
    logger.debug(
        f'Start async migration {migration_name}'
    )

    # Get db cursor
    from django.db import connections
    cursor = connections[db_alias].cursor()
    for table in tables:
        index_sql = create_index_sql(table['table_name'], table['index_name'], table['column_name'])
        fk_sql = create_fk_sql(table['table_name'], table['fk_constraint'], table['column_name'], "task_completion",
                               "id")

        # Run index_sql
        cursor.execute(index_sql)
        cursor.execute(fk_sql)

    migration.status = AsyncMigrationStatus.STATUS_FINISHED
    migration.save(using=db_alias)
    logger.debug(
        f'Async migration {migration_name} complete'
    )

def reverse_migration(migration_name, db_alias):
    migration = AsyncMigrationStatus.objects.using(db_alias).create(
        name=migration_name,
        status=AsyncMigrationStatus.STATUS_STARTED,
    )
    logger.debug(
        f'Start async migration {migration_name}'
    )

    # Get db cursor
    from django.db import connections
    cursor = connections[db_alias].cursor()
    for table in tables:
        reverse_sql = drop_index_sql(table['table_name'], table['index_name'], table['column_name'])
        # Run reverse_sql
        cursor.execute(reverse_sql)

    migration.status = AsyncMigrationStatus.STATUS_FINISHED
    migration.save(using=db_alias)
    logger.debug(
        f'Async migration {migration_name} complete'
    )


def forwards(apps, schema_editor):
    # Dispatch migrations to rqworkers
    db_alias = schema_editor.connection.alias
    start_job_async_or_sync(forward_migration, migration_name=migration_name, db_alias=db_alias)


def backwards(apps, schema_editor):
    db_alias = schema_editor.connection.alias
    start_job_async_or_sync(reverse_migration, migration_name=migration_name, db_alias=db_alias)


def get_operations():
    logger.info(f'IS_SQLITE: {IS_SQLITE}')
    if not IS_SQLITE:
        return [
            migrations.RunPython(forwards, backwards),
        ]

    operations = []
    # Use standard migration for SQLITE
    for table in tables:
        operations.append(
            migrations.AlterField(
                model_name=table['model_name'],
                name='annotation',
                field=models.ForeignKey(on_delete=models.deletion.CASCADE,
                                        related_name=table['table_name'],
                                        to='tasks.annotation'),
            ),
        )
    return operations


class Migration(migrations.Migration):
    atomic = False

    dependencies = [
        ('tasks', '0047_merge_20240318_2210'),
        ('io_storages', '0016_add_aws_sse_kms_key'),
    ]

    operations = get_operations()
