# -*- coding: utf-8 -*-
from django.db import transaction
from requests.exceptions import RequestException

from events.accounts.models import User, GrantTransitionInfo
from events.accounts.utils import TransitionEmail
from events.celery_app import app

SENDER_RETRY_DELAY = 300
SENDER_RETRY_ERRORS = (RequestException, )
SENDER_RETRIES = 3
SENDER_RETRY_BACKOFF = 60


@app.task(
    bind=True,
    default_retry_delay=SENDER_RETRY_DELAY,
    autoretry_for=SENDER_RETRY_ERRORS,
    retry_kwargs={'max_retries': SENDER_RETRIES},
    retry_backoff=SENDER_RETRY_BACKOFF,
)
def send_transition_email(self, new_user, objects):
    email = TransitionEmail()
    response = email.send_email(new_user, objects)
    if response:
        response.raise_for_status()
        return response.status_code, response.text, response.headers.get('content-type')


def get_transition_objects(queryset):
    objects = {}
    for item in queryset:
        if item.old_user not in objects:
            objects[item.old_user] = {}
        if item.content_type not in objects[item.old_user]:
            objects[item.old_user][item.content_type] = []
        objects[item.old_user][item.content_type].append(item.object_pk)
    return objects


def make_transition_email(user_id):
    new_user = User.objects.get(pk=user_id)
    queryset = (
        GrantTransitionInfo.objects.filter(new_user__pk=user_id)
        .select_related('old_user', 'content_type')
        .select_for_update(skip_locked=True)
    )
    with transaction.atomic():
        objects = get_transition_objects(queryset)
        send_transition_email.delay(new_user, objects)
        queryset.delete()


@app.task
def make_transition_emails():
    while True:
        user_id = (
            GrantTransitionInfo.objects.values_list('new_user', flat=True)
            .distinct().order_by('?').first()
        )
        if not user_id:
            break

        make_transition_email(user_id)
