# Generated by Django 4.2.7 on 2023-12-04 11:09


import logging
import uuid

from django.db import migrations, models

from firefighter.incidents.models.impact import LevelChoices

logger = logging.getLogger(__name__)


def remap_incidents(apps, schema_editor):
    ImpactLevel = apps.get_model("incidents", "ImpactLevel")
    Impact = apps.get_model("incidents", "Impact")

    to_delete_name = "Few employees with minor issues"
    to_delete_value = LevelChoices.LOW.value
    impactlevel_to_delete = ImpactLevel.objects.filter(name=to_delete_name).first()

    new_name = "Significant issues for some employees"
    new_value = LevelChoices.MEDIUM.value  # before remapping of impact level because after remapping "Significant issues for some employees" will refer to "LO"
    impactlevel = ImpactLevel.objects.filter(name=new_name).first()

    if impactlevel_to_delete is None:
        logger.error(f"Failed to find ImpactLevel to delete {to_delete_value} {to_delete_name}.")
        return
    if impactlevel is None:
        logger.error(f"Failed to find ImpactLevel {new_value} {new_name}.")
        return
    impacts = Impact.objects.filter(impact_level=impactlevel_to_delete)

    for impact in impacts:
        try:
            impact.impact_level = impactlevel
            impact.save()
        except Exception:
            logger.exception(f"Failed to find ImpactLevel {new_value} {new_name}.")

    try:
        impactlevel_to_delete.delete()
    except Exception:
        logger.exception(f"Failed to delete impact level {to_delete_value} {to_delete_name}.")


def update_impact_levels(apps, schema_editor):
    ImpactLevel = apps.get_model("incidents", "ImpactLevel")

    emoji_mapping = {
        "HT": "⏫",
        "HI": "🔼",
        "MD": "▶️",
        "LO": "🔽",
        "LT": "⏬",
        "NO": "",
    }

    updates = [
        {
            "old_name": "Critical issue for many customers",
            "old_value": "HI",
            "new_name": None,
            "new_value": "HT",
            "new_order": 5,
        },
        {
            "old_name": "Some customers have issues",
            "old_value": "MD",
            "new_name": "Some customers with major issues",
            "new_value": "HI",
            "new_order": 4,
        },
        {
            "old_name": "Few customers with minor issues",
            "old_value": "LO",
            "new_name": "Some customers with significant issues",
            "new_value": "MD",
            "new_order": 3,
        },
        {
            "old_name": "No impact on customers",
            "old_value": "N/A",
            "new_name": None,
            "new_value": "LT",
            "new_order": 1,
        },
        {
            "old_name": "Key services inaccessible for most",
            "old_value": "HI",
            "new_name": "Critical issues for many sellers",
            "new_value": "HT",
            "new_order": 5,
        },
        {
            "old_name": "Some sellers have significant issues",
            "old_value": "MD",
            "new_name": "Some sellers with major issues",
            "new_value": "HI",
            "new_order": 4,
        },
        {
            "old_name": "Few sellers with minor issues",
            "old_value": "LO",
            "new_name": "Some sellers with significant issues",
            "new_value": "MD",
            "new_order": 3,
        },
        {
            "old_name": "No impact on sellers",
            "old_value": "N/A",
            "new_name": None,
            "new_value": "LT",
            "new_order": 1,
        },
        {
            "old_name": "Significant issues for some employees",
            "old_value": "MD",
            "new_name": "Major issues for internal users",
            "new_value": "LO",
            "new_order": 2,
        },
        {
            "old_name": "Critical internal tools down",
            "old_value": "HI",
            "new_name": "Critical issues for internal users",
            "new_value": "MD",
            "new_order": 3,
        },
        {
            "old_name": "No impact on employees",
            "old_value": "N/A",
            "new_name": "Minor issues for internal users",
            "new_value": "LT",
            "new_order": 1,
        },
        {
            "old_name": "Whole business or revenue at risk",
            "old_value": "HI",
            "new_name": "Critical business impact",
            "new_value": "HT",
            "new_order": 5,
        },
        {
            "old_name": "Significant business or revenue loss",
            "old_value": "MD",
            "new_name": "Major business impact",
            "new_value": "HI",
            "new_order": 4,
        },
        {
            "old_name": "Minor impact on business or revenue",
            "old_value": "LO",
            "new_name": "Significant business impact",
            "new_value": "MD",
            "new_order": 3,
        },
        {
            "old_name": "No impact on business or revenue",
            "old_value": "N/A",
            "new_name": None,
            "new_value": "LT",
            "new_order": 1,
        },
    ]

    for update in updates:
        old_name = update["old_name"]
        try:
            impact_level = ImpactLevel.objects.filter(name=old_name).first()
            if not impact_level:
                logger.error(f"Failed to find ImpactLevel with old name:'{old_name}'.")
                continue
            if update["new_name"] is not None:
                impact_level.name = old_name
            impact_level.value = update["new_value"]
            impact_level.order = update["new_order"]
            impact_level.emoji = emoji_mapping.get(update["new_value"], impact_level.emoji)
            impact_level.save()
        except Exception:
            logger.exception(f"Failed to update ImpactLevel '{old_name}'.")

    logger.info("Successfully updated new ImpactLevels.")


def add_impact_levels(apps, schema_editor):

    ImpactLevel = apps.get_model("incidents", "ImpactLevel")
    ImpactType = apps.get_model("incidents", "ImpactType")

    adds = [
        {

            "name": "Some customers with minor issues",
            "value": LevelChoices.LOW.value,
            "order": 2,
            "impact_type_id": 3,
            "emoji": LevelChoices.LOW.emoji
        },
        {
            "name": "Some sellers with minor issues",
            "value": LevelChoices.LOW.value,
            "order": 2,
            "impact_type_id": 2,
            "emoji": LevelChoices.LOW.emoji
        },
        {
            "name": "Minor business impact",
            "value": LevelChoices.LOW.value,
            "order": 2,
            "impact_type_id": 1,
            "emoji": LevelChoices.LOW.emoji
        },
        {

            "name": "N/A",
            "value": LevelChoices.NONE.value,
            "order": 0,
            "impact_type_id": 1,
            "emoji": LevelChoices.NONE.emoji
        },
        {

            "name": "N/A",
            "value": LevelChoices.NONE.value,
            "order": 0,
            "impact_type_id": 2,
            "emoji": LevelChoices.NONE.emoji
        },
        {

            "name": "N/A",
            "value": LevelChoices.NONE.value,
            "order": 0,
            "impact_type_id": 3,
            "emoji": LevelChoices.NONE.emoji
        },
        {

            "name": "N/A",
            "value": LevelChoices.NONE.value,
            "order": 0,
            "impact_type_id": 4,
            "emoji": LevelChoices.NONE.emoji
        },
    ]

    for add in adds:
        name = add["name"]
        try:
            impact_type_id = add["impact_type_id"]
            impact_level = ImpactLevel.objects.filter(name=name, impact_type_id=impact_type_id).first()
            impact_type = ImpactType.objects.filter(id=impact_type_id).first()
            if not impact_type:
                logger.error(f"There is no impact type id:'{impact_type_id}'.")
                continue
            if impact_level:
                logger.error(f"There is already an impact level with name:'{name}' and type:'{impact_type_id}'.")
                continue
            new_impact_level = ImpactLevel(
                name=name,
                value=add["value"],
                order=add["order"],
                emoji=add["emoji"],
                impact_type=impact_type,
            )
            new_impact_level.save()
        except Exception:
            logger.exception(f"Failed to create new ImpactLevel {name}.")

    logger.info("Successfully created new ImpactLevels.")


class Migration(migrations.Migration):

    dependencies = [
        ("incidents", "0007_update_component_name"),
    ]

    operations = [
        migrations.AlterField(
            model_name="impactlevel",
            name="emoji",
            field=models.CharField(default="", max_length=5),
        ),
        migrations.RemoveConstraint(
          model_name="impactlevel",
          name="incidents_impactlevel_value_valid",
        ),
        migrations.AddConstraint(
            model_name="impactlevel",
            constraint=models.CheckConstraint(
                check=models.Q(("value__in", ["HT", "HI", "MD", "LO", "LT", "NO"])),
                name="incidents_impactlevel_value_valid",
            ),
        ),
        migrations.AlterField(
            model_name="impactlevel",
            name="id",
            field=models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False),
        ),
        migrations.RunPython(remap_incidents),
        migrations.RunPython(update_impact_levels),
        migrations.RunPython(add_impact_levels),
    ]
