# Generated by Django 3.2.23 on 2024-01-19 16:59

import base64

from django.db import migrations

from allauth.mfa.adapter import get_adapter
from allauth.mfa.models import Authenticator
from django_otp.plugins.otp_static.models import StaticDevice
from django_otp.plugins.otp_totp.models import TOTPDevice


def move_mfa(apps, schema_editor):
    """Data migration to switch to django-allauth's new built-in MFA."""
    adapter = get_adapter()
    authenticators = []
    for totp in TOTPDevice.objects.filter(confirmed=True).iterator():
        recovery_codes = set()
        for sdevice in StaticDevice.objects.filter(
            confirmed=True, user_id=totp.user_id
        ).iterator():
            recovery_codes.update(sdevice.token_set.values_list('token', flat=True))
        secret = base64.b32encode(bytes.fromhex(totp.key)).decode('ascii')
        totp_authenticator = Authenticator(
            user_id=totp.user_id,
            type=Authenticator.Type.TOTP,
            data={'secret': adapter.encrypt(secret)},
        )
        authenticators.append(totp_authenticator)
        authenticators.append(
            Authenticator(
                user_id=totp.user_id,
                type=Authenticator.Type.RECOVERY_CODES,
                data={'migrated_codes': [adapter.encrypt(c) for c in recovery_codes]},
            )
        )
    Authenticator.objects.bulk_create(authenticators)


class Migration(migrations.Migration):
    dependencies = [('users', '0012_alter_ruleset_can_view'),
        ('otp_static', '0002_throttling'),
        ('otp_totp', '0002_auto_20190420_0723'),
        ('mfa', '0002_authenticator_timestamps'),]

    operations = [
        migrations.RunPython(move_mfa, reverse_code=migrations.RunPython.noop)
    ]
