# Generated by Django 5.2.4 on 2025-11-06 23:01

import django.db.models.deletion
from django.db import migrations, models


def migrate_vod_logos_forward(apps, schema_editor):
    """
    Migrate VOD logos from the Logo table to the new VODLogo table.
    This copies all logos referenced by movies or series to VODLogo.
    Uses pure SQL for maximum performance.
    """
    from django.db import connection

    print("\n" + "="*80)
    print("Starting VOD logo migration...")
    print("="*80)

    with connection.cursor() as cursor:
        # Step 1: Copy unique logos from Logo table to VODLogo table
        # Only copy logos that are used by movies or series
        print("Copying logos to VODLogo table...")
        cursor.execute("""
            INSERT INTO vod_vodlogo (name, url)
            SELECT DISTINCT l.name, l.url
            FROM dispatcharr_channels_logo l
            WHERE l.id IN (
                SELECT DISTINCT logo_id FROM vod_movie WHERE logo_id IS NOT NULL
                UNION
                SELECT DISTINCT logo_id FROM vod_series WHERE logo_id IS NOT NULL
            )
            ON CONFLICT (url) DO NOTHING
        """)
        print(f"Created VODLogo entries")

        # Step 2: Update movies to point to VODLogo IDs using JOIN
        print("Updating movie references...")
        cursor.execute("""
            UPDATE vod_movie m
            SET logo_id = v.id
            FROM dispatcharr_channels_logo l
            INNER JOIN vod_vodlogo v ON l.url = v.url
            WHERE m.logo_id = l.id
            AND m.logo_id IS NOT NULL
        """)
        movie_count = cursor.rowcount
        print(f"Updated {movie_count} movies with new VOD logo references")

        # Step 3: Update series to point to VODLogo IDs using JOIN
        print("Updating series references...")
        cursor.execute("""
            UPDATE vod_series s
            SET logo_id = v.id
            FROM dispatcharr_channels_logo l
            INNER JOIN vod_vodlogo v ON l.url = v.url
            WHERE s.logo_id = l.id
            AND s.logo_id IS NOT NULL
        """)
        series_count = cursor.rowcount
        print(f"Updated {series_count} series with new VOD logo references")

    print("="*80)
    print("VOD logo migration completed successfully!")
    print(f"Summary: Updated {movie_count} movies and {series_count} series")
    print("="*80 + "\n")


def migrate_vod_logos_backward(apps, schema_editor):
    """
    Reverse migration - moves VODLogos back to Logo table.
    This recreates Logo entries for all VODLogos and updates Movie/Series references.
    """
    Logo = apps.get_model('dispatcharr_channels', 'Logo')
    VODLogo = apps.get_model('vod', 'VODLogo')
    Movie = apps.get_model('vod', 'Movie')
    Series = apps.get_model('vod', 'Series')

    print("\n" + "="*80)
    print("REVERSE: Moving VOD logos back to Logo table...")
    print("="*80)

    # Get all VODLogos
    vod_logos = VODLogo.objects.all()
    print(f"Found {vod_logos.count()} VOD logos to reverse migrate")

    # Create Logo entries for each VODLogo
    logos_to_create = []
    vod_to_logo_mapping = {}  # VODLogo ID -> Logo ID

    for vod_logo in vod_logos:
        # Check if a Logo with this URL already exists
        existing_logo = Logo.objects.filter(url=vod_logo.url).first()

        if existing_logo:
            # Logo already exists, just map to it
            vod_to_logo_mapping[vod_logo.id] = existing_logo.id
            print(f"Logo already exists for URL: {vod_logo.url[:50]}... (using existing)")
        else:
            # Create new Logo entry
            new_logo = Logo(name=vod_logo.name, url=vod_logo.url)
            logos_to_create.append(new_logo)

    # Bulk create new Logo entries
    if logos_to_create:
        print(f"Creating {len(logos_to_create)} new Logo entries...")
        Logo.objects.bulk_create(logos_to_create, ignore_conflicts=True)
        print("Logo entries created")

        # Get the created Logo instances with their IDs
        for vod_logo in vod_logos:
            if vod_logo.id not in vod_to_logo_mapping:
                try:
                    logo = Logo.objects.get(url=vod_logo.url)
                    vod_to_logo_mapping[vod_logo.id] = logo.id
                except Logo.DoesNotExist:
                    print(f"Warning: Could not find Logo for URL: {vod_logo.url[:100]}...")

    print(f"Created mapping for {len(vod_to_logo_mapping)} VOD logos -> Logos")

    # Update movies to point back to Logo table
    movie_count = 0
    for movie in Movie.objects.exclude(logo__isnull=True):
        if movie.logo_id in vod_to_logo_mapping:
            movie.logo_id = vod_to_logo_mapping[movie.logo_id]
            movie.save(update_fields=['logo_id'])
            movie_count += 1
    print(f"Updated {movie_count} movies to use Logo table")

    # Update series to point back to Logo table
    series_count = 0
    for series in Series.objects.exclude(logo__isnull=True):
        if series.logo_id in vod_to_logo_mapping:
            series.logo_id = vod_to_logo_mapping[series.logo_id]
            series.save(update_fields=['logo_id'])
            series_count += 1
    print(f"Updated {series_count} series to use Logo table")

    # Delete VODLogos (they're now redundant)
    vod_logo_count = vod_logos.count()
    vod_logos.delete()
    print(f"Deleted {vod_logo_count} VOD logos")

    print("="*80)
    print("Reverse migration completed!")
    print(f"Summary: Created/reused {len(vod_to_logo_mapping)} logos, updated {movie_count} movies and {series_count} series")
    print("="*80 + "\n")


def cleanup_migrated_logos(apps, schema_editor):
    """
    Delete Logo entries that were successfully migrated to VODLogo.

    Uses efficient JOIN-based approach with LEFT JOIN to exclude channel usage.
    """
    from django.db import connection

    print("\n" + "="*80)
    print("Cleaning up migrated Logo entries...")
    print("="*80)

    with connection.cursor() as cursor:
        # Single efficient query using JOINs:
        # - JOIN with vod_vodlogo to find migrated logos
        # - LEFT JOIN with channels to find which aren't used
        cursor.execute("""
            DELETE FROM dispatcharr_channels_logo
            WHERE id IN (
                SELECT l.id
                FROM dispatcharr_channels_logo l
                INNER JOIN vod_vodlogo v ON l.url = v.url
                LEFT JOIN dispatcharr_channels_channel c ON c.logo_id = l.id
                WHERE c.id IS NULL
            )
        """)
        deleted_count = cursor.rowcount

    print(f"✓ Deleted {deleted_count} migrated Logo entries (not used by channels)")
    print("="*80 + "\n")


class Migration(migrations.Migration):

    dependencies = [
        ('vod', '0002_add_last_seen_with_default'),
        ('dispatcharr_channels', '0013_alter_logo_url'),  # Ensure Logo table exists
    ]

    operations = [
        # Step 1: Create the VODLogo model
        migrations.CreateModel(
            name='VODLogo',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=255)),
                ('url', models.TextField(unique=True)),
            ],
            options={
                'verbose_name': 'VOD Logo',
                'verbose_name_plural': 'VOD Logos',
            },
        ),

        # Step 2: Remove foreign key constraints temporarily (so we can change the IDs)
        # We need to find and drop the actual constraint names dynamically
        migrations.RunSQL(
            sql=[
                # Drop movie logo constraint (find it dynamically)
                """
                DO $$
                DECLARE
                    constraint_name text;
                BEGIN
                    SELECT conname INTO constraint_name
                    FROM pg_constraint
                    WHERE conrelid = 'vod_movie'::regclass
                    AND conname LIKE '%logo_id%fk%';

                    IF constraint_name IS NOT NULL THEN
                        EXECUTE 'ALTER TABLE vod_movie DROP CONSTRAINT ' || constraint_name;
                    END IF;
                END $$;
                """,
                # Drop series logo constraint (find it dynamically)
                """
                DO $$
                DECLARE
                    constraint_name text;
                BEGIN
                    SELECT conname INTO constraint_name
                    FROM pg_constraint
                    WHERE conrelid = 'vod_series'::regclass
                    AND conname LIKE '%logo_id%fk%';

                    IF constraint_name IS NOT NULL THEN
                        EXECUTE 'ALTER TABLE vod_series DROP CONSTRAINT ' || constraint_name;
                    END IF;
                END $$;
                """,
            ],
            reverse_sql=[
                # The AlterField operations will recreate the constraints pointing to VODLogo,
                # so we don't need to manually recreate them in reverse
                migrations.RunSQL.noop,
            ],
        ),

        # Step 3: Migrate the data (this copies logos and updates references)
        migrations.RunPython(migrate_vod_logos_forward, migrate_vod_logos_backward),

        # Step 4: Now we can safely alter the foreign keys to point to VODLogo
        migrations.AlterField(
            model_name='movie',
            name='logo',
            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='movie', to='vod.vodlogo'),
        ),
        migrations.AlterField(
            model_name='series',
            name='logo',
            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='series', to='vod.vodlogo'),
        ),

        # Step 5: Clean up migrated Logo entries
        migrations.RunPython(cleanup_migrated_logos, migrations.RunPython.noop),
    ]
