from django.db import migrations


def backfill_emails(apps, schema_editor):
    """
    Make every existing row satisfy `email` being unique and non-blank, BEFORE
    the constraint that requires it is added in 0003.

    Two things can be wrong in the existing table, and both are silent until
    the AlterField fails halfway through a deploy:

    - `email` was `blank=True` and is genuinely empty. The local database has
      exactly one such row (the developer's superuser). It gets a placeholder
      at `.invalid`, which is the reserved TLD precisely so it can never route
      mail; the account owner changes it in the admin afterwards.
    - Two rows differ only by case. The new manager lowercases the whole
      address, so `Sam@x.com` and `sam@x.com` would collide under the
      constraint. The later row keeps its identity through a `+N` tag rather
      than being merged, because merging accounts is not something a migration
      may decide.

    Reversing is a no-op: the addresses written here are valid values for the
    old column too, and guessing which of them used to be blank is worse than
    leaving them.
    """
    User = apps.get_model('users', 'CustomUser')

    seen = set()
    for user in User.objects.order_by('pk').iterator():
        email = (user.email or '').strip().lower()

        if not email:
            email = f'{user.username or f"user-{user.pk}"}@invalid.local'

        if email in seen:
            local, _, domain = email.partition('@')
            suffix = 2
            while f'{local}+{suffix}@{domain}' in seen:
                suffix += 1
            email = f'{local}+{suffix}@{domain}'

        seen.add(email)

        if email != user.email:
            user.email = email
            user.save(update_fields=['email'])


class Migration(migrations.Migration):

    dependencies = [
        ('users', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(backfill_emails, migrations.RunPython.noop),
    ]
