# Generated by Django 2.1.3 on 2018-11-24 23:20

from django.db import migrations, IntegrityError, transaction

# This can be ran multiple times, I got your back ;)
def populate_nickname(apps, schema_editor):
    from django.db.models import Subquery, OuterRef
    from ...core.conf import settings
    User = apps.get_model(settings.AUTH_USER_MODEL)
    UserProfile = apps.get_model("spirit_user", "UserProfile")
    first_user = UserProfile.objects.first()
    if first_user and not first_user.nickname:
        UserProfile.objects.all().update(
            nickname=Subquery(
                User.objects
                .filter(pk=OuterRef('user_id'))
                .values('username')[:1]))

def make_usernames_lower(apps, schema_editor):
    from django.db.models.functions import Lower
    from django.db.models import Count
    from ...core.conf import settings
    User = apps.get_model(settings.AUTH_USER_MODEL)

    if settings.ST_CASE_INSENSITIVE_USERNAMES:
        try:
            with transaction.atomic():
                User.objects.all().update(
                    username=Lower('username'))
        except IntegrityError:
            # Show all duplicated usernames
            users_lower = (
                User.objects
                .annotate(username_lower=Lower('username'))
                .values('username_lower')
                .annotate(cnt=Count(Lower('username')))
                .values('username_lower', 'cnt')
                .filter(cnt__gt=1)
                .order_by('username_lower', 'cnt'))
            users = [
                u.username
                for u in (
                    User.objects
                    .annotate(username_lower=Lower('username'))
                    .filter(username_lower__in=[
                        u['username_lower'] for u in users_lower]))]
            raise IntegrityError(
                'There are two or more users with '
                'similar name but different casing, for example: '
                'someUser and SomeUser, either remove one of them '
                'or set the `ST_CASE_INSENSITIVE_USERNAMES` setting '
                'to False. Then run the upgrade/migration again. '
                'Any change was reverted. Duplicate users are {}'.format(users))


class Migration(migrations.Migration):

    dependencies = [
        ('spirit_user', '0010_userprofile_nickname'),
    ]

    operations = [
        migrations.RunPython(populate_nickname),
        migrations.RunPython(make_usernames_lower)
    ]
