# Generated by Django 3.2.18 on 2023-06-06 14:57

from django.db import migrations


def make_sure_service_name_is_unique(service_list, parent, cache):
    """
    Args:
        service_list (list): Service instances that are associated to Devices or Virtual Machines.
        parent (str): could be either "device" or "virtual_machine".
        cache (dict): dictionary that contains Device/Virtual Machine instances as Key and associated Service instances' names as Value.
    """
    for service in service_list:
        host = getattr(service, parent)
        service_names = cache.setdefault(host, set())
        count = 1
        service_name = service.name
        while service_name in service_names:
            appendage = f"_{count}"
            len_appendage = len(appendage)
            length_overflow = len(service_name) + len_appendage - 100
            if length_overflow > 0:
                service_name = service_name[: len(service_name) - length_overflow]
            service_name += appendage
            count += 1

        if service_name != service.name:
            print(f'    Service instance {service.id} is being renamed to "{service_name}" for uniqueness')
            service.name = service_name
            service.save()
        cache[host].add(service_name)


def ensure_all_existing_services_fit_uniqueness_constraints(apps, schema_editor):
    """
    Migration function to ensure that all existing Service instances fit the uniqueness constraints [name, device] or [name, vm]
    By enumerating Service instances associated with a device/vm and appending unique indices to names of the Service instances.
    """
    Service = apps.get_model("ipam", "Service")
    device_services = Service.objects.filter(device__isnull=False)
    device_to_service = {}
    make_sure_service_name_is_unique(device_services, "device", device_to_service)

    vm_services = Service.objects.filter(virtual_machine__isnull=False)
    vm_to_service = {}
    make_sure_service_name_is_unique(vm_services, "virtual_machine", vm_to_service)


class Migration(migrations.Migration):
    dependencies = [
        ("ipam", "0034_status_nonnullable"),
    ]

    operations = [
        migrations.RunPython(ensure_all_existing_services_fit_uniqueness_constraints, migrations.RunPython.noop),
    ]
