# Generated by Django 4.2.16 on 2024-11-20 17:08

import django.db.models.deletion
import django.db.models.functions.datetime
from django.db import migrations, models
from django.db.migrations.state import StateApps
from django.db.models import Q
from django.utils.timezone import localdate

# Before the club role rework, the maximum free role
# was the hardcoded highest non-board role
MAXIMUM_FREE_ROLE = 1


def migrate_meta_groups(apps: StateApps, schema_editor):
    """Attach the existing meta groups to the clubs.

    Until now, the meta groups were not attached to the clubs,
    nor to the users.
    This creates actual foreign relationships between the clubs
    and theirs groups and the users and theirs groups.

    Warnings:
        When the meta groups associated with the clubs aren't found,
        they are created.
        Thus the migration shouldn't fail, and all the clubs will
        have their groups.
        However, there will probably be some groups that have
        not been found but exist nonetheless,
        so there will be duplicates and dangling groups.
        There must be a manual cleanup after this migration.
    """
    Group = apps.get_model("core", "Group")
    Club = apps.get_model("club", "Club")

    meta_groups = Group.objects.filter(is_meta=True)
    clubs = list(Club.objects.all())
    for club in clubs:
        club.board_group = meta_groups.get_or_create(
            name=f"{club.unix_name}-bureau", defaults={"is_meta": True}
        )[0]
        club.members_group = meta_groups.get_or_create(
            name=f"{club.unix_name}-membres", defaults={"is_meta": True}
        )[0]
        club.save()
        club.refresh_from_db()
        memberships = club.members.filter(
            Q(end_date=None) | Q(end_date__gt=localdate())
        ).select_related("user")
        club.members_group.users.set([m.user for m in memberships])
        club.board_group.users.set(
            [m.user for m in memberships.filter(role__gt=MAXIMUM_FREE_ROLE)]
        )


# steps of the migration :
# - Create a nullable field for the board group and the member group
# - Edit those new fields to make them point to currently existing meta groups
# - When this data migration is done, make the fields non-nullable
class Migration(migrations.Migration):
    dependencies = [
        ("core", "0040_alter_user_options_user_user_permissions_and_more"),
        ("club", "0011_auto_20180426_2013"),
    ]

    operations = [
        migrations.RemoveField(
            model_name="club",
            name="edit_groups",
        ),
        migrations.RemoveField(
            model_name="club",
            name="owner_group",
        ),
        migrations.RemoveField(
            model_name="club",
            name="view_groups",
        ),
        migrations.AddField(
            model_name="club",
            name="board_group",
            field=models.OneToOneField(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="club_board",
                to="core.group",
            ),
        ),
        migrations.AddField(
            model_name="club",
            name="members_group",
            field=models.OneToOneField(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="club",
                to="core.group",
            ),
        ),
        migrations.RunPython(
            migrate_meta_groups, reverse_code=migrations.RunPython.noop, elidable=True
        ),
    ]
