from django.db import migrations, models
from django.db.models import Count
from django.db.models.functions import Lower


def normalize_existing_user_emails(apps, schema_editor):
    User = apps.get_model("users", "User")
    db_alias = schema_editor.connection.alias

    duplicates = (
        User.objects.using(db_alias)
        .annotate(email_lower=Lower("email"))
        .values("email_lower")
        .annotate(total=Count("id"))
        .filter(total__gt=1)
    )

    if duplicates.exists():
        duplicate_values = ", ".join(
            row["email_lower"] for row in duplicates[:5] if row["email_lower"]
        )
        raise RuntimeError(
            "Cannot apply case-insensitive email uniqueness because duplicate emails "
            f"exist by case: {duplicate_values}"
        )

    User.objects.using(db_alias).update(email=Lower("email"))


class Migration(migrations.Migration):

    dependencies = [
        ("users", "0002_remove_user_username"),
    ]

    operations = [
        migrations.RunPython(
            normalize_existing_user_emails, reverse_code=migrations.RunPython.noop
        ),
        migrations.AddConstraint(
            model_name="user",
            constraint=models.UniqueConstraint(
                Lower("email"), name="users_email_ci_unique"
            ),
        ),
    ]
