import logging

from typing import Dict, List

from django.db import transaction
from django.template import loader

from intranet.femida.src.actionlog.decorators import action_logged
from intranet.femida.src.notifications.utils import get_base_context
from intranet.femida.src.oebs.api import OebsAPI
from intranet.femida.src.oebs.choices import LOGIN_LOOKUP_DOCUMENT_TYPES
from intranet.femida.src.offers.choices import (
    CITIZENSHIP,
    OFFER_DOCS_PROCESSING_STATUSES as DOCS_STATUSES,
    OFFER_DOCS_PROCESSING_RESOLUTIONS as DOCS_RESOLUTIONS,
)
from intranet.femida.src.startrek.operations import IssueCommentOperation
from intranet.femida.src.yt.tasks import save_offer_data_in_yt


logger = logging.getLogger(__name__)


def _get_docs_for_login_check(candidate) -> Dict[str, str]:
    """
    Отдаёт словарь с документами для проверки наличия ФЛ в OeBS.
    :return: {тип документа: номер документа}
    """
    result = {}
    verification = candidate.verifications.alive().first()
    warn_template = (
        f'Cannot check login in OeBS: %s; '
        f'candidate_id: {candidate.id}, '
        f'verification_id: {verification and verification.id}'
    )

    if not verification:
        logger.warning(warn_template, 'no verification')
        return result

    if not verification.raw_data.get('params'):
        logger.warning(warn_template, 'no verification params')
        return result

    if verification.inn:
        result[LOGIN_LOOKUP_DOCUMENT_TYPES.inn] = verification.inn
    else:
        logger.warning(warn_template, 'no inn')

    if verification.snils:
        result[LOGIN_LOOKUP_DOCUMENT_TYPES.snils] = verification.snils
    else:
        logger.warning(warn_template, 'no snils')

    return result


def _get_logins(docs: Dict[str, str]) -> List[str]:
    """
    Отдаёт список логинов ФЛ в OeBS, если они были найдены
    :param docs: {тип документа: номер документа}
    :return: отсортированный список логинов
    """
    result = set()
    for document_type, document_id in docs.items():
        login = OebsAPI.get_login_by_document(document_type, document_id)
        if login:
            result.add(login)
    return sorted(result)


def _invite_hr_manager(offer, logins=None):
    context = get_base_context()
    context['instance'] = offer
    context['logins'] = logins or []
    comment = loader.render_to_string('startrek/offers/oebs-person-check.wiki', context)
    operation = IssueCommentOperation(offer.startrek_hr_key)
    operation.delay(comment)


@transaction.atomic
@action_logged('offer_check_oebs_login')
def check_oebs_login(offer) -> None:
    """
    Ищет в OEBS, был ли у нас такой сотрудник, и отправляет комментарий с результатом в тикет.
    Если сотрудника не было, ставит задачу на распознавание документов в Янге.
    Если возникают какие-либо трудности с поиском либо с последующим созданием ФЛ в Оракле,
    переводит HR-тикет на менеджера.
    """
    docs_for_check = _get_docs_for_login_check(offer.candidate)
    logins = _get_logins(docs_for_check)

    offer.docs_processing_status = DOCS_STATUSES.finished

    if not docs_for_check:
        offer.docs_processing_resolution = DOCS_RESOLUTIONS.skipped_no_docs_to_check
    elif logins:
        offer.docs_processing_resolution = DOCS_RESOLUTIONS.skipped_person_found
    elif not offer.org.is_russian:
        offer.docs_processing_resolution = DOCS_RESOLUTIONS.skipped_oohrc_org
    elif offer.profile.citizenship != CITIZENSHIP.RU:
        offer.docs_processing_resolution = DOCS_RESOLUTIONS.skipped_foreigner
    # Note: если мы изначально не получили от кандидата нужные "необязательные" документы,
    # у нас нет морального права автоматически запрашивать их повторно
    elif not all((offer.passport_pages, offer.snilses)):
        offer.docs_processing_resolution = DOCS_RESOLUTIONS.skipped_no_docs_to_process
    else:
        offer.docs_processing_status = DOCS_STATUSES.in_progress
        save_offer_data_in_yt.delay(offer.id)

    offer.save(update_fields=('docs_processing_status', 'docs_processing_resolution'))
    _invite_hr_manager(offer, logins)
