# Generated by Django 5.1.12 on 2025-09-12 08:38

import django.db.models.deletion
import pgtrigger.compiler
import pgtrigger.migrations
import psqlextra.backend.migrations.operations.apply_state
import psqlextra.backend.migrations.operations.create_materialized_view_model
import psqlextra.indexes.unique_index
import psqlextra.manager.manager
import psqlextra.models.view
import uuid

from django.apps.registry import Apps
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor


def migrate_parents(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
    Group = apps.get_model("authentik_core", "Group")
    db_alias = schema_editor.connection.alias

    for group in Group.objects.using(db_alias).all():
        if not group.parent:
            continue
        group.parents.add(group.parent)
        group.save()


class Migration(migrations.Migration):

    dependencies = [
        ("authentik_core", "0054_alter_application_meta_icon_alter_source_icon"),
    ]

    operations = [
        migrations.CreateModel(
            name="GroupParentageNode",
            fields=[
                (
                    "uuid",
                    models.UUIDField(
                        default=uuid.uuid4, editable=False, primary_key=True, serialize=False
                    ),
                ),
            ],
            options={
                "verbose_name": "Group Parentage Node",
                "verbose_name_plural": "Group Parentage Nodes",
                "db_table": "authentik_core_groupparentage",
            },
        ),
        migrations.AddField(
            model_name="groupparentagenode",
            name="child",
            field=models.ForeignKey(
                on_delete=django.db.models.deletion.CASCADE,
                related_name="parent_nodes",
                to="authentik_core.group",
            ),
        ),
        migrations.AddField(
            model_name="groupparentagenode",
            name="parent",
            field=models.ForeignKey(
                on_delete=django.db.models.deletion.CASCADE,
                related_name="child_nodes",
                to="authentik_core.group",
            ),
        ),
        psqlextra.backend.migrations.operations.create_materialized_view_model.PostgresCreateMaterializedViewModel(
            name="GroupAncestryNode",
            fields=[
                (
                    "id",
                    models.AutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
            ],
            options={
                "db_table": "authentik_core_groupancestry",
            },
            view_options={
                "query": (
                    "\n            WITH RECURSIVE accumulator AS (\n                SELECT\n                child_id::text || '-' || parent_id::text as id,\n                child_id AS descendant_id,\n                parent_id AS ancestor_id\n                FROM authentik_core_groupparentage\n\n                UNION\n\n                SELECT\n                accumulator.descendant_id::text || '-' || current.parent_id::text as id,\n                accumulator.descendant_id,\n                current.parent_id AS ancestor_id\n                FROM accumulator\n                JOIN authentik_core_groupparentage current\n                ON accumulator.ancestor_id = current.child_id\n            )\n            SELECT * FROM accumulator\n        ",
                    (),
                ),
            },
            bases=(psqlextra.models.view.PostgresMaterializedViewModel,),
            managers=[
                ("objects", psqlextra.manager.manager.PostgresManager()),
            ],
        ),
        psqlextra.backend.migrations.operations.apply_state.ApplyState(
            state_operation=migrations.AddField(
                model_name="groupancestrynode",
                name="ancestor",
                field=models.ForeignKey(
                    on_delete=django.db.models.deletion.DO_NOTHING,
                    related_name="descendant_nodes",
                    to="authentik_core.group",
                ),
            ),
        ),
        psqlextra.backend.migrations.operations.apply_state.ApplyState(
            state_operation=migrations.AddField(
                model_name="groupancestrynode",
                name="descendant",
                field=models.ForeignKey(
                    on_delete=django.db.models.deletion.DO_NOTHING,
                    related_name="ancestor_nodes",
                    to="authentik_core.group",
                ),
            ),
        ),
        migrations.AddIndex(
            model_name="groupancestrynode",
            index=models.Index(fields=["descendant"], name="authentik_c_descend_f83a71_idx"),
        ),
        migrations.AddIndex(
            model_name="groupancestrynode",
            index=models.Index(fields=["ancestor"], name="authentik_c_ancesto_974845_idx"),
        ),
        migrations.AddIndex(
            model_name="groupancestrynode",
            index=psqlextra.indexes.unique_index.UniqueIndex(
                fields=["id"], name="authentik_c_id_5d0bb4_idx"
            ),
        ),
        pgtrigger.migrations.AddTrigger(
            model_name="groupparentagenode",
            trigger=pgtrigger.compiler.Trigger(
                name="refresh_groupancestry",
                sql=pgtrigger.compiler.UpsertTriggerSql(
                    func="\n                    REFRESH MATERIALIZED VIEW CONCURRENTLY authentik_core_groupancestry;\n                    RETURN NULL;\n                ",
                    hash="a987621714359aa0389e03fd2d52f86b118e7d24",
                    operation="INSERT OR UPDATE OR DELETE",
                    pgid="pgtrigger_refresh_groupancestry_62450",
                    table="authentik_core_groupparentage",
                    when="AFTER",
                ),
            ),
        ),
        migrations.AddField(
            model_name="group",
            name="parents",
            field=models.ManyToManyField(
                blank=True,
                related_name="children",
                through="authentik_core.GroupParentageNode",
                to="authentik_core.group",
            ),
        ),
        migrations.RunPython(migrate_parents, migrations.RunPython.noop),
    ]
