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

from __future__ import unicode_literals

from django.conf import settings
from django.core.cache import cache
from django.shortcuts import redirect, reverse
from django.utils.translation import gettext as _
from django.views.generic.base import TemplateView

from common.exceptions import JMSException
from common.utils import get_logger, FlashMessageUtil
from orgs.utils import tmp_to_root_org
from tickets.const import TicketType
from tickets.errors import AlreadyClosed
from tickets.models import (
    Ticket, ApplyAssetTicket,
    ApplyLoginTicket, ApplyLoginAssetTicket, ApplyCommandTicket
)
from users.models import User

logger = get_logger(__name__)

__all__ = ['TicketDirectApproveView']


class TicketDirectApproveView(TemplateView):
    template_name = 'tickets/approve_check_password.html'
    redirect_field_name = 'next'

    TICKET_SUB_MODEL_MAP = {
        TicketType.apply_asset: ApplyAssetTicket,
        TicketType.login_confirm: ApplyLoginTicket,
        TicketType.login_asset_confirm: ApplyLoginAssetTicket,
        TicketType.command_confirm: ApplyCommandTicket,
    }

    @property
    def message_data(self):
        return {
            'title': _('Ticket approval'),
            'error': _("This ticket does not exist, "
                       "the process has ended, or this link has expired"),
            'redirect_url': self.login_url,
            'auto_redirect': False
        }

    @property
    def login_url(self):
        return reverse('authentication:login') + f'?admin=1&{self.redirect_field_name}=/'

    def redirect_message_response(self, **kwargs):
        message_data = self.message_data
        for key, value in kwargs.items():
            if isinstance(value, str):
                message_data[key] = value
        if message_data.get('message'):
            message_data.pop('error')
        redirect_url = FlashMessageUtil.gen_message_url(message_data)
        return redirect(redirect_url)

    @staticmethod
    def clear(token):
        cache.delete(token)

    def get_context_data(self, **kwargs):
        # 放入工单信息
        kwargs.update({
            'content': kwargs['ticket_info'].get('content', []),
            'prompt_msg': _('Click the button below to approve or reject'),
        })
        return super().get_context_data(**kwargs)

    def get(self, request, *args, **kwargs):
        if not (settings.TICKETS_DIRECT_APPROVE or request.user.is_authenticated):
            direct_url = reverse('tickets:direct-approve', kwargs={'token': kwargs['token']})
            redirect_url = f"{reverse('authentication:login') + '?admin=1'}&{self.redirect_field_name}={direct_url}"
            message_data = {
                'title': _('Ticket approval'),
                'message': _('After successful authentication, this ticket can be approved directly'),
                'redirect_url': redirect_url,
                'auto_redirect': True,
            }
            redirect_url = FlashMessageUtil.gen_message_url(message_data)
            return redirect(redirect_url)

        ticket_info = cache.get(kwargs['token'])
        if not ticket_info:
            return self.redirect_message_response(redirect_url=self.login_url)
        return super().get(request, ticket_info=ticket_info, *args, **kwargs)

    @staticmethod
    def get_user(request, ticket_info):
        user = request.user
        if not user.is_authenticated and settings.TICKETS_DIRECT_APPROVE:
            user_id = ticket_info.get('approver_id')
            user = User.objects.filter(id=user_id).first()
        return user

    def post(self, request, **kwargs):
        token = kwargs.get('token')
        action = request.POST.get('action')
        if action not in ['approve', 'reject']:
            msg = _('Illegal approval action')
            return self.redirect_message_response(error=str(msg))

        ticket_info = cache.get(token)
        if not ticket_info:
            return self.redirect_message_response(redirect_url=self.login_url)
        try:
            user = self.get_user(request, ticket_info)
            ticket_id = ticket_info.get('ticket_id')
            with tmp_to_root_org():
                ticket = Ticket.all().get(id=ticket_id)
                ticket_sub_model = self.TICKET_SUB_MODEL_MAP[ticket.type]
                ticket = ticket_sub_model.objects.get(id=ticket_id)
            if not ticket.has_current_assignee(user):
                raise JMSException(_("This user is not authorized to approve this ticket"))
            getattr(ticket, action)(user)
        except AlreadyClosed as e:
            self.clear(token)
            return self.redirect_message_response(error=str(e), redirect_url=self.login_url)
        except Exception as e:
            return self.redirect_message_response(error=str(e), redirect_url=self.login_url)

        self.clear(token)
        return self.redirect_message_response(message=_("Success"), redirect_url=self.login_url)
