# Generated by Django 3.2.20 on 2023-07-18 09:53

from django.db import migrations, models
import django_migration_linter as linter
from django.db.models import Count

from common.database import get_random_readonly_database_key_if_present_otherwise_default


def fix_duplicate_orders(apps, schema_editor):
    EscalationPolicy = apps.get_model('alerts', 'EscalationPolicy')

    # it should be safe to use a readonly database because duplicates are pretty infrequent
    db = get_random_readonly_database_key_if_present_otherwise_default()

    # find all (escalation_chain_id, order) tuples that have more than one entry (meaning duplicates)
    items_with_duplicate_orders = EscalationPolicy.objects.using(db).values(
        "escalation_chain_id", "order"
    ).annotate(count=Count("order")).order_by().filter(count__gt=1)  # use order_by() to reset any existing ordering

    # make sure we don't fix the same escalation chain more than once
    escalation_chain_ids = set(item["escalation_chain_id"] for item in items_with_duplicate_orders)

    for escalation_chain_id in escalation_chain_ids:
        policies = EscalationPolicy.objects.filter(escalation_chain_id=escalation_chain_id).order_by("order", "id")
        # assign correct sequential order for each policy starting from 0
        for idx, policy in enumerate(policies):
            policy.order = idx
        EscalationPolicy.objects.bulk_update(policies, fields=["order"])


class Migration(migrations.Migration):

    dependencies = [
        ('alerts', '0023_auto_20230718_0952'),
    ]

    operations = [
        linter.IgnoreMigration(),  # adding a unique constraint after fixing duplicates should be fine
        migrations.AlterModelOptions(
            name='escalationpolicy',
            options={'ordering': ['order']},
        ),
        migrations.AlterField(
            model_name='escalationpolicy',
            name='order',
            field=models.PositiveIntegerField(db_index=True, editable=False, null=True),
        ),
        migrations.RunPython(fix_duplicate_orders, migrations.RunPython.noop),
        migrations.AddConstraint(
            model_name='escalationpolicy',
            constraint=models.UniqueConstraint(fields=('escalation_chain_id', 'order'), name='unique_escalation_policy_order'),
        ),
    ]
