# -*- coding: utf-8 -*-

import logging

from django.conf import settings
from django.core.mail import EmailMessage
from django.template.loader import render_to_string, get_template, TemplateDoesNotExist
from django.utils import six
from django.utils.encoding import force_text
from django.utils.translation import ugettext as _, override

from idm.core.constants.email_templates import TEMPLATE_TYPES
from idm.notification.models import Notice
from idm.notification.qr import generate_qr
from idm.users.models import User
from idm.utils.human import inflect
from ids.registry import registry


log = logging.getLogger(__name__)


def render_notification_body(message_templates, context):
    template_name = None
    if isinstance(message_templates, (list, tuple)):
        for template in message_templates:
            try:
                get_template(template)
                template_name = template
                break
            except TemplateDoesNotExist:
                continue
    else:
        template_name = message_templates

    if template_name.endswith('html'):
        extension = 'html'
        content_subtype = 'html'
    else:
        extension = 'txt'
        content_subtype = 'plain'
    context['template_name'] = template_name
    body = render_to_string('emails/notice_form.%s' % extension, context)
    return body, content_subtype


def send_notification(subject, message_templates, recipients, context=None, headers=None, from_email=None, cc=None,
                      attachments=None):
    """
    Формирует и отправляет сообщение и сохраняет его в таблице уведомлений.
    Для уволенных сотрудников письмо не отправляется.
    subject - тема сообщения
    message_templates - имя шаблона или список имен шаблонов, обрабатываются аналогично render_to_string
    recipients - получатели сообщения
    context - словарь переменных контекста для шаблона
    headers - добавочные заголовки (reply-to и тп)
    from_email - адрес отправителя, если не указан берется из настроек
    cc - список адресов, на которые сообщение также должно быть отправлено (в базу не пишем)
    """

    # ToDo: перенести в сеттинги после https://st.yandex-team.ru/IDM-7788
    attachments = attachments or []
    if context is None:
        context = {}

    # RULES-1094: Прикладываем QR-код с длинным паролем
    try:
        role = context.get('role')
        password = context.get('password')
        if role is not None and isinstance(password, str) and role.node.slug_path == '/role/long/':
            attachments.append(('password.gif', generate_qr(password), 'image/gif'))
    except Exception as e:
        log.warning('Strange data in email context (%s): %s', context, e)

    message_body, content_subtype = render_notification_body(message_templates, context)
    message_body = message_body.strip()
    email = None

    for recipient in recipients:
        message = message_body
        if isinstance(recipient, User):
            if content_subtype == 'plain' and recipient.first_name:
                message = render_to_string('emails/head.txt', {'user': recipient}) + message
            # сначала сохраним уведомление в базе
            Notice.objects.create(subject=force_text(subject), message=message, recipient=recipient)
            email_address = recipient.email if recipient.email else None
        elif isinstance(recipient, six.string_types) and recipient:
            email_address = recipient
        else:
            email_address = None
        if email_address is not None:
            email = EmailMessage(
                subject=_(subject),
                from_email=from_email or settings.FROM_EMAIL,
                headers=headers,
                cc=cc,
                attachments=attachments,
                body=message,
                to=[email_address],
            )
            email.content_subtype = content_subtype
            try:
                email.send()
            except Exception:
                log.warning('Cannot send an email', exc_info=1)

    if email is None:
        log.warning('no recipients for message %s', message_body)
        return


def report_problem(subject, message_templates, context=None, system=None, security_cc=False, incident=False,
                   fallback_to_reponsibles=False):
    from idm.core.models import System

    if security_cc:
        recipients = list(settings.EMAILS_FOR_REPORTS)
    else:
        recipients = list(settings.EMAILS_FOR_PROBLEMS)

    if system is not None:
        assert isinstance(system, System)
        recipients += system.get_emails(fallback_to_reponsibles)

    send_notification(subject, message_templates, recipients, context)
    if incident:
        incident_emails = list(settings.EMAILS_FOR_INCIDENTS)
        send_notification(subject, message_templates, incident_emails, context)


def get_issues_repository():
    issues_repository = registry.get_repository(
        'startrek2',
        'issues',
        user_agent=settings.IDM_ROBOT_USERNAME,
        oauth_token=settings.IDM_TRACKER_OAUTH_TOKEN,
        timeout=settings.IDM_TRACKER_TIMEOUT,
    )
    return issues_repository


def create_issue(queue, summary, description, components, followers=()):
    repository = get_issues_repository()
    repository.create(
        type='task',
        queue=queue,
        summary=summary,
        description=description,
        components=components,
        followers=list(followers),
    )


def create_sox_incosistency_issue(system, report):
    title = 'Нарушение консистентности в SOX-системе {}'.format(system.get_name(lang='ru'))
    body, _ = render_notification_body(['emails/service/report_check_roles.txt'], {'report': report})
    create_issue(
        queue=settings.IDM_TRACKER_INCONSISTENCY_QUEUE,
        summary=title,
        description=body,
        components=settings.IDM_TRACKER_INCONSISTENCY_COMPONENTS,
    )


def create_removing_from_ad_groups_issue(users):
    body = render_to_string(
        'emails/service/removing_from_ad_groups.txt',
        {
            'users': ','.join(u.username for u in users),
            'old_users': settings.AD_LDAP_OLD_USERS_OU,
        }
    )
    repository = get_issues_repository()
    return repository.create(
        type='task',
        queue=settings.IDM_TRACKER_REMOVE_FROM_AD_GROUPS_QUEUE,
        summary='Не удалось удалить пользователей из групп в AD',
        description=body,
        components=None,
        followers=[],
    )


def create_blocking_in_ad_issue(users):
    body = render_to_string(
        'emails/service/blocking_in_ad.txt',
        {
            'users': ','.join(u.username for u in users),
        }
    )
    repository = get_issues_repository()
    return repository.create(
        type='task',
        queue=settings.IDM_TRACKER_REMOVE_FROM_AD_GROUPS_QUEUE,
        summary='Не удалось заблокировать пользователей в AD',
        description=body,
        components=None,
        followers=[],
    )


def send_reminder(subject, templates, allow_external_recepients=False, **kwargs):
    responsibles, template_type = subject.get_reminder_recipients_and_template_type(allow_external_recepients)
    subj, template = templates[template_type]
    context = {'subject': subject}
    context.update(kwargs)
    if template_type != TEMPLATE_TYPES.SELF_USER:
        subj %= inflect('чего', subject.get_name())
    for responsible in responsibles:
        with override(responsible.lang_ui):
            context['user'] = responsible
            send_notification(subj, template, [responsible], context)
