# Generated by Django 5.2.16 on 2026-07-20 07:31

from django.conf import settings
from django.db import migrations, models


def collapse_strategic_objectives(apps, schema_editor):
    """Fold legacy Strategic-Objective rows into their framework container.

    The M&E framework treats the Strategic Objective as the framework itself
    (LogFrame), so the chain roots at Impact. Any existing ``strategic_objective``
    row is removed after re-rooting its direct children (Impacts) to no parent;
    its description is preserved on the container when that has none.
    """
    LogFrame = apps.get_model("mel_indicators", "LogFrame")
    LogFrameRow = apps.get_model("mel_indicators", "LogFrameRow")

    for so in LogFrameRow.objects.filter(level="strategic_objective"):
        # Re-root the SO's direct children (Impacts) — they now hang directly
        # off the Strategic Objective container, with no parent row.
        LogFrameRow.objects.filter(parent=so).update(parent=None)
        lf = LogFrame.objects.filter(pk=so.logframe_id).first()
        if (
            lf is not None
            and not (lf.description or "").strip()
            and (so.description or "").strip()
        ):
            lf.description = so.description
            lf.save(update_fields=["description"])

    # SO rows now have no children; a queryset delete bypasses the model-level
    # delete() guard, which is safe once the children have been re-rooted.
    LogFrameRow.objects.filter(level="strategic_objective").delete()


def noop_reverse(apps, schema_editor):
    # Irreversible: Strategic-Objective rows are folded into their container and
    # cannot be reconstructed from the collapsed data.
    pass


class Migration(migrations.Migration):

    dependencies = [
        (
            "mel_indicators",
            "0017_remove_disaggregationcategory_uniq_disagg_category_per_indicator_and_more",
        ),
        ("rims_finance", "0014_gl_entries_bank_statements"),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.RunPython(collapse_strategic_objectives, noop_reverse),
        migrations.AlterField(
            model_name="historicallogframe",
            name="code",
            field=models.CharField(
                blank=True,
                help_text="M&E framework — Strategic Objective code (unique when set).",
                max_length=40,
            ),
        ),
        migrations.AlterField(
            model_name="historicallogframe",
            name="planning_period",
            field=models.CharField(
                blank=True,
                help_text="M&E framework — planning period this Strategic Objective covers (e.g. 2024–2028).",
                max_length=60,
            ),
        ),
        migrations.AlterField(
            model_name="historicallogframerow",
            name="level",
            field=models.CharField(
                choices=[
                    ("impact", "Impact"),
                    ("outcome", "Intermediate Outcome"),
                    ("output", "Output"),
                    ("activity", "Activity"),
                    ("input", "Input"),
                ],
                max_length=24,
            ),
        ),
        migrations.AlterField(
            model_name="logframe",
            name="code",
            field=models.CharField(
                blank=True,
                help_text="M&E framework — Strategic Objective code (unique when set).",
                max_length=40,
            ),
        ),
        migrations.AlterField(
            model_name="logframe",
            name="planning_period",
            field=models.CharField(
                blank=True,
                help_text="M&E framework — planning period this Strategic Objective covers (e.g. 2024–2028).",
                max_length=60,
            ),
        ),
        migrations.AlterField(
            model_name="logframerow",
            name="level",
            field=models.CharField(
                choices=[
                    ("impact", "Impact"),
                    ("outcome", "Intermediate Outcome"),
                    ("output", "Output"),
                    ("activity", "Activity"),
                    ("input", "Input"),
                ],
                max_length=24,
            ),
        ),
        migrations.AlterConstraint(
            model_name="logframe",
            name="uniq_logframe_code",
            constraint=models.UniqueConstraint(
                condition=models.Q(("code__gt", "")),
                fields=("code",),
                name="uniq_logframe_code",
                violation_error_message="A Strategic Objective with this code already exists.",
            ),
        ),
    ]
