# Generated by Django 2.2.24 on 2021-07-07 17:46

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


def migrate_data_from_old_model_to_new_model_up(apps, schema_editor):
    """ Move objects from AnsibleCollectionDeprecated to NewAnsibleCollectionDeprecated."""
    AnsibleCollectionDeprecated = apps.get_model('ansible', 'AnsibleCollectionDeprecated')
    NewAnsibleCollectionDeprecated = apps.get_model('ansible', 'NewAnsibleCollectionDeprecated')
    AnsibleRepository = apps.get_model('ansible', 'AnsibleRepository')
    latest_repo_versions = []
    for repo in AnsibleRepository.objects.all():
        latest_repo_versions.append(repo.versions.exclude(complete=False).latest().pk)

    for deprecated_collection in AnsibleCollectionDeprecated.objects.filter(repository_version_id__in=latest_repo_versions):
        NewAnsibleCollectionDeprecated(
            namespace=deprecated_collection.collection.namespace,
            name=deprecated_collection.collection.name,
            pulp_type="ansible.collection_deprecation",
            collection_id=deprecated_collection.collection_id,
            repository_id=deprecated_collection.repository_version.repository.pk,
            version_added_id=deprecated_collection.repository_version.pk,
        ).save()


def migrate_data_from_old_model_to_new_model_down(apps, schema_editor):
    """ Move objects from NewAnsibleCollectionDeprecated to AnsibleCollectionDeprecated."""
    AnsibleCollectionDeprecated = apps.get_model('ansible', 'AnsibleCollectionDeprecated')
    NewAnsibleCollectionDeprecated = apps.get_model('ansible', 'NewAnsibleCollectionDeprecated')
    RepositoryVersionContentDetails = apps.get_model('core', 'RepositoryVersionContentDetails')
    for deprecation in NewAnsibleCollectionDeprecated.objects.all():
        AnsibleCollectionDeprecated(
            collection_id=deprecation.collection_id,
            repository_version_id=deprecation.version_added_id,
        ).save()
        deprecation.version_memberships.all().delete()
    RepositoryVersionContentDetails.objects.filter(content_type="ansible.collection_deprecation").delete()


def create_repository_content_for_deprecation(apps, schema_editor):
    """ Create RepositoryContent for AnsibleCollectionDeprecated."""
    AnsibleCollectionDeprecated = apps.get_model('ansible', 'AnsibleCollectionDeprecated')
    RepositoryContent = apps.get_model('core', 'RepositoryContent')
    RepositoryVersionContentDetails = apps.get_model('core', 'RepositoryVersionContentDetails')
    repo_content = []
    counts_list = []
    count = defaultdict(int)

    # Create RepositoryContent with deduplicated deprecation items
    for name, namespace in AnsibleCollectionDeprecated.objects.values_list("name", "namespace").distinct():
        new_deprecation = AnsibleCollectionDeprecated.objects.create(pulp_type="ansible.collection_deprecation", name=name, namespace=namespace)
        for deprecation in AnsibleCollectionDeprecated.objects.filter(name=name, namespace=namespace, repository_id__isnull=False):
            repo_content.append(RepositoryContent(
                    content=new_deprecation,
                    repository_id=deprecation.repository_id,
                    version_added_id=deprecation.version_added_id,
                ))
            count[deprecation.version_added_id] += 1
            if len(repo_content) >= 1024:
                RepositoryContent.objects.bulk_create(repo_content)
                repo_content.clear()
    RepositoryContent.objects.bulk_create(repo_content)
    repo_content.clear()
    AnsibleCollectionDeprecated.objects.filter(repository_id__isnull=False).delete()

    # Update Repository content counts
    for repo_version_id, total in count.items():
        count_obj = RepositoryVersionContentDetails(
            content_type="ansible.collection_deprecation",
            repository_version_id=repo_version_id,
            count=total,
            count_type="A", # Added
        )
        counts_list.append(count_obj)

        count_obj = RepositoryVersionContentDetails(
            content_type="ansible.collection_deprecation",
            repository_version_id=repo_version_id,
            count=total,
            count_type="P", # Present
        )
        counts_list.append(count_obj)
        if len(counts_list) >= 1024:
            RepositoryVersionContentDetails.objects.bulk_create(counts_list)
            counts_list.clear()

    RepositoryVersionContentDetails.objects.bulk_create(counts_list)


def create_deprecation_from_repository_content(apps, schema_editor):
    """ Create AnsibleCollectionDeprecated from RepositoryContent."""
    AnsibleCollectionDeprecated = apps.get_model('ansible', 'AnsibleCollectionDeprecated')
    Collection = apps.get_model('ansible', 'Collection')

    for deprecation in AnsibleCollectionDeprecated.objects.all():
        col = Collection.objects.get(namespace=deprecation.namespace, name=deprecation.name)
        for repo_content in deprecation.version_memberships.all():
            AnsibleCollectionDeprecated.objects.create(
                name=deprecation.name,
                namespace=deprecation.namespace,
                collection_id=col.pk,
                repository_id=repo_content.repository_id,
                version_added_id = repo_content.version_added_id,
            )

    AnsibleCollectionDeprecated.objects.filter(repository_id__isnull=True).delete()


class Migration(migrations.Migration):

    dependencies = [
        ('core', '0068_add_timestamp_of_interest'),
        ('ansible', '0034_handle_jsonfield_warnings'),
    ]

    operations = [
        migrations.CreateModel(
            name='NewAnsibleCollectionDeprecated',
            fields=[
                ('content_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='ansible_ansiblecollectiondeprecated', serialize=False, to='core.Content')),
                ('namespace', models.CharField(editable=False, max_length=64)),
                ('name', models.CharField(editable=False, max_length=64)),
                ('collection_id',  models.UUIDField(editable=False, primary_key=False, serialize=False, null=True)),
                ('repository_id',  models.UUIDField(editable=False, primary_key=False, serialize=False, null=True)),
                ('version_added_id',  models.UUIDField(editable=False, primary_key=False, serialize=False, null=True)),
            ],
            options={
                'default_related_name': '%(app_label)s_%(model_name)s',
            },
            bases=('core.content',),
        ),
        migrations.RunPython(
            code=migrate_data_from_old_model_to_new_model_up,
            reverse_code=migrate_data_from_old_model_to_new_model_down,
        ),
        migrations.DeleteModel(
            name='AnsibleCollectionDeprecated',
        ),
        migrations.RenameModel(
            old_name='NewAnsibleCollectionDeprecated',
            new_name='AnsibleCollectionDeprecated',
        ),
        migrations.RunPython(
            code=create_repository_content_for_deprecation,
            reverse_code=create_deprecation_from_repository_content,
        ),
    ]
