from datetime import datetime
from typing import Optional, TYPE_CHECKING, List, Dict
import urllib3

from django.conf import settings
from django.db.models import NOT_PROVIDED
from django.utils import timezone
from idm.core.canonical import MultiDecision, UserMultiDecision
from idm.utils import http

if TYPE_CHECKING:
    from idm.core.models import Transfer
    from idm.users.models import Group, User

STAFF_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
STAFF_DATE_FORMAT = '%Y-%m-%d'


def get_last_sync_date():
    from idm.core.models import Action
    now = timezone.now()

    qs = Action.objects.filter(action='transfers_decided', added__lt=now).order_by('-added')
    date = None
    while True:
        action = qs.first()
        if action is None:
            break
        if action.data['status'] == 0:
            date = action.added
            break
        else:
            qs = qs.filter(pk__lt=action.pk)
    return date


def get_group_transfers(group: 'Group', from_date: str, to_date: str, retries: urllib3.Retry) -> List[Dict]:
    url = settings.STAFF_TRANSFERS_URL + group.slug
    response = http.get(
        url,
        params={'from': from_date, 'to': to_date},
        headers={'Authorization': 'OAuth %s' % settings.IDM_STAFF_OAUTH_TOKEN},
        max_retries=retries,
        use_client_certificate=False,
    ).json()
    return response['result']


def get_user_transfers(user: 'User', from_date: str, to_date: str, retries: urllib3.Retry) -> List[Dict]:
    response = http.get(
        settings.STAFF_USER_TRANSFERS_URL,
        params={'from_date': from_date, 'to_date': to_date, 'person': user.username},
        headers={'Authorization': 'OAuth %s' % settings.IDM_STAFF_OAUTH_TOKEN},
        max_retries=retries,
        use_client_certificate=False,
    ).json()
    result = response['proposals'] + response['rotations']

    # ручка возвращает только перемещения, при которых меняются обязанности
    for x in result:
        x['changing_duties'] = True

    return result


def get_transfer_decision(transfer: 'Transfer', from_date=None, to_date=None, last_sync_date=NOT_PROVIDED):
    from idm.core.models import Transfer

    max_retries = urllib3.Retry(
        total=settings.IDM_NEWHIRE_RETRIES_COUNT,
        backoff_factor=settings.IDM_NEWHIRE_BACKOFF_FACTOR,
        status_forcelist=settings.IDM_NEWHIRE_STATUS_FORCELIST,
    )

    if transfer.type == Transfer.TYPE_GROUP:
        date_format = STAFF_DATETIME_FORMAT
    else:
        date_format = STAFF_DATE_FORMAT

    now = timezone.now()
    if to_date is None:
        to_date = now
    if from_date is None:
        from_date = last_sync_date if last_sync_date is not NOT_PROVIDED else get_last_sync_date()
    if from_date is None:
        # предполалаем, что в настройках дата уже строкой в нужном формате
        from_date = settings.STAFF_TRANSFERS_INITIAL_DATE
    else:
        from_date = from_date.strftime(date_format)
    to_date = to_date.strftime(date_format)

    if transfer.type == Transfer.TYPE_GROUP:
        transfers = get_group_transfers(transfer.group, from_date, to_date, max_retries)
        decision = MultiDecision.from_list(transfers)
    else:
        transfers = get_user_transfers(transfer.user, from_date, to_date, max_retries)
        decision = UserMultiDecision.from_list(transfers)

    return decision
