# -*- coding: utf-8 -*-
#
from django.utils import translation
from django.utils.translation import gettext_noop
from django.contrib.auth.mixins import UserPassesTestMixin
from django.http.response import JsonResponse
from rest_framework import permissions
from rest_framework.request import Request

from common.exceptions import UserConfirmRequired
from common.utils import i18n_fmt
from audits.handler import create_or_update_operate_log
from audits.const import ActionChoices, ActivityChoices
from audits.models import ActivityLog

__all__ = [
    "PermissionsMixin",
    "RecordViewLogMixin",
    "UserConfirmRequiredExceptionMixin",
]


class UserConfirmRequiredExceptionMixin:
    """
    异常处理
    """

    def dispatch(self, request, *args, **kwargs):
        try:
            return super().dispatch(request, *args, **kwargs)
        except UserConfirmRequired as e:
            return JsonResponse(e.detail, status=e.status_code)


class PermissionsMixin(UserPassesTestMixin):
    permission_classes = [permissions.IsAuthenticated]
    request: Request

    def get_permissions(self):
        return self.permission_classes

    def test_func(self):
        permission_classes = self.get_permissions()
        for permission_class in permission_classes:
            if not permission_class().has_permission(self.request, self):
                return False
        return True


class RecordViewLogMixin:
    ACTION = ActionChoices.view

    @staticmethod
    def _filter_params(params):
        new_params = {}
        need_pop_params = ('format', 'order')
        for key, value in params.items():
            if key in need_pop_params:
                continue
            if isinstance(value, list):
                value = list(filter(None, value))
            if value:
                new_params[key] = value
        return new_params

    def get_resource_display(self, request):
        query_params = dict(request.query_params)
        params = self._filter_params(query_params)

        spm_filter = params.pop("spm", None)

        if not params and not spm_filter:
            display_message = gettext_noop("Export all")
        elif spm_filter:
            display_message = gettext_noop("Export only selected items")
        else:
            query = ",".join(
                ["%s=%s" % (key, value) for key, value in params.items()]
            )
            display_message = i18n_fmt(gettext_noop("Export filtered: %s"), query)
        return display_message

    def record_logs(self, ids, **kwargs):
        resource_type = self.model._meta.verbose_name
        create_or_update_operate_log(
            self.ACTION, resource_type, force=True, **kwargs
        )
        detail = i18n_fmt(
            gettext_noop('User %s view/export secret'), self.request.user
        )
        activities = [
            ActivityLog(
                resource_id=getattr(resource_id, 'pk', resource_id),
                type=ActivityChoices.operate_log, detail=detail
            )
            for resource_id in ids
        ]
        ActivityLog.objects.bulk_create(activities)

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        with translation.override('en'):
            resource_display = self.get_resource_display(request)
            ids = [q.id for q in self.get_queryset()]
            self.record_logs(ids, resource_display=resource_display)
        return response

    def retrieve(self, request, *args, **kwargs):
        response = super().retrieve(request, *args, **kwargs)
        with translation.override('en'):
            resource = self.get_object()
            self.record_logs([resource.id], resource=resource)
        return response