from django.db import transaction


@transaction.atomic
def as_view(request, *args, **kwargs):
    from django.contrib.auth.hashers import make_password

    from users.utils.interfaces import Interface, Response
    from users.serializers import UserCreateSerializer
    from users.utils.services import CreateService
    from users.utils.t import RSL, request_updater
    from users.models import User as UserModel, Role as RoleModel

    from rest_framework.exceptions import ValidationError

    # First, query on db.
    username = request.data.get('username')
    phone_number = request.data.get('phone_number')
    email_address = request.data.get('email_address')
    password = request.data.get('password')

    notification_platform = []

    if username:
        obj = UserModel.objects.filter(username=username).first()
        if obj:
            raise ValidationError({'username': 'A user with these characteristics exists.'})
    if phone_number:
        obj = UserModel.objects.filter(phone_number=phone_number).first()
        if obj:
            raise ValidationError({'phone_number': 'A user with these characteristics exists.'})
        notification_platform.append('SMS')
    if email_address:
        obj = UserModel.objects.filter(email_address=email_address).first()
        if obj:
            raise ValidationError({'email_address': 'A user with these characteristics exists.'})
        notification_platform.append('Email')

    password = password if username else (RSL() if email_address or phone_number else None)
    password = make_password(password) if password else None
    username = username if username else (RSL() if email_address or phone_number else None)

    if not ((username and password) or email_address or phone_number):
        raise ValidationError(
            {"detail": (
                "To register as a user, you must enter either a username and password, "
                "a phone number, or an email address."
            )})

    request_updater(request, password=password, username=username)
    # Next, we create a new record in the database for the input information.
    interface = Interface(
        request=request,
        args=args,
        kwargs=kwargs,
        service=CreateService(
            model=UserModel,
            serializer_class=UserCreateSerializer,
        ),
    )
    ret = interface()

    # Finally, we send the generated password to the entered phone number.
    user_id = ret.data.get('id')
    obj = UserModel.objects.get(id=user_id)

    roleids = request.data.getlist('roles')
    roles = []
    if roleids:

        for id_ in roleids:
            try:
                r = RoleModel.objects.get(id=id_)
                roles.append(r)
            except:
                continue
    if roles:
        obj.roles.add(*roles)

    if notification_platform:
        obj.send_verification_code(platforms=notification_platform)
    ret.data['roles'] = [
        {
            'id': r.id,
            'title': r.title,
        } for r in roles
    ]
    return ret
