# coding: utf-8
import logging

import urllib3
from django.conf import settings
from django.db import transaction

import constance

from idm.core.constants.action import ACTION
from idm.users.models import User
from idm.utils import http
from idm.utils.actions import start_stop_actions

log = logging.getLogger(__name__)


def get_gaps():
    logins = list(User.objects.users().active().values_list('username', flat=True))

    json_data = {
        'use_calendar': 0,
        'person_logins': logins,
    }

    max_retries = urllib3.Retry(
        total=settings.IDM_GAP_RETRIES_COUNT,
        backoff_factor=settings.IDM_GAP_BACKOFF_FACTOR,
        status_forcelist=settings.IDM_GAP_STATUS_FORCELIST,
    )

    response = http.post(
        settings.GAP_URL,
        headers={'Authorization': 'OAuth %s' % settings.IDM_GAP_OAUTH_TOKEN},
        use_client_certificate=False,
        timeout=settings.IDM_GAP_TIMEOUT,
        max_retries=max_retries,
        json=json_data,
    )

    if response.status_code != 200:
        log.error('Wrong status: %s. Content: %s', response.status_code, response.content[:10000])
        response.raise_for_status()

    gaps = response.json()

    return gaps


def perform_chunked_gap_update(ids, value, chunk_size=1000):
    """
        Обновляет статус отсутствия
    """
    for start_index in range(0, len(ids), chunk_size):
        with transaction.atomic():
            ids_block = (
                User.objects
                .users()
                .filter(pk__in=ids[start_index: start_index + chunk_size])
                .order_by('pk')
                .lock_by_select()
            )
            User.objects.filter(pk__in=ids_block).update(is_absent=value)


def sync_gaps_for_all_users():
    """
        Ставит всем сотрудникам is_absent=True, если у него суммарное количество отсутствия >= 10 часов.
        Всем остальным ставит is_absent=False
    """

    with start_stop_actions(ACTION.GAP_SYNCHRONIZATION_STARTED, ACTION.GAP_SYNCHRONIZATION_COMPLETED) as manager:
        try:
            absenters = []
            gaps = get_gaps()

            for login, data in gaps['persons'].items():
                if data['available_seconds'] < constance.config.GAP_THRESHOLD:
                    absenters.append(login)

            absent_ids = (
                User.objects
                .users()
                .active()
                .filter(username__in=absenters, is_absent=False)
                .order_by('id')
                .values_list('id', flat=True)
            )
            present_ids = (
                User.objects
                .users()
                .active()
                .filter(is_absent=True)
                .exclude(username__in=absenters)
                .order_by('id')
                .values_list('id', flat=True)
            )

            perform_chunked_gap_update(absent_ids, True)
            perform_chunked_gap_update(present_ids, False)

        except Exception as e:
            log.warning('Fetching gaps for all users failed', exc_info=True)
            manager.on_failure({'error': str(e)})
            # чтобы в __exit__ создался Action с ошибкой
            raise e
