# coding: utf-8
"""统一响应"""
import logging
import re

from rest_framework.response import Response
from rest_framework import exceptions
from rest_framework import status, serializers
from .service_code import (INFO_CODE, VERIFICATION_ERROR, AUTHENTICATION_ERROR,
                           SERVICE_ERROR, USER_NOT_FOUND, PASSWORD_WRONG,
                           THIRD_PARTY_API_ERROR, PERMISSIONE_RROR,
                           TOO_MANY_LINES, SEARCH_NO_FOUND, NETWORK_ERROR,
                           MYSQL_OPERATE_ERROR)
from common.third_party_api.exceptions import CallApiError
from django.db.utils import ProgrammingError
from .return_structure import error_message
from common.utils.serializers import err_msg

logger = logging.getLogger("")


def custom_exception_handler(exc, context):
    """
        Returns the response that should be used for any given exception.

        By default we handle the REST framework `APIException`, and also
        Django's built-in `Http404` and `PermissionDenied` exceptions.

        Any unhandled exceptions may return `None`, which will cause a 500
        error to be raised.
    """
    if isinstance(exc, ServiceHandleException):
        return exc.response
    elif isinstance(exc, OpenApiServiceHandleException):
        return exc.response
    elif isinstance(exc, exceptions.AuthenticationFailed):
        logger.exception(exc)
        data = error_message(msg=str(exc.detail),
                             msg_show="用户认证失败",
                             code=AUTHENTICATION_ERROR)
        return Response(data, status=status.HTTP_401_UNAUTHORIZED)
    elif isinstance(exc, ValidationError):
        logger.exception(exc)
        return exc.response
    elif isinstance(exc, serializers.ValidationError):
        logger.exception(exc)
        msg_list = []
        if isinstance(exc.detail, dict):
            for i, j in exc.detail.items():
                msg_list.append("%s: %s" % (i, '、'.join([err_msg.get(x.code, "参数错误") for x in j])))
        data = error_message(msg=str(exc.detail),
                             msg_show=", ".join(msg_list),
                             code=VERIFICATION_ERROR)
        return Response(data, status=status.HTTP_400_BAD_REQUEST)
    elif isinstance(exc, AuthenticationError):
        return exc.response
    elif isinstance(exc, CallApiError):
        logger.debug(exc.message)
        data = error_message(code=THIRD_PARTY_API_ERROR,
                             msg=str(exc.message.get("msg")),
                             msg_show="第三方api请求错误")
        return Response(data, status=status.HTTP_400_BAD_REQUEST)
    elif isinstance(exc, ProgrammingError):
        rst = re.search(r"^.*Table '(.*)' doesn't exist", str(exc))
        print(exc)
        if rst:
            data = error_message(code=MYSQL_OPERATE_ERROR, msg_show="未找到数据")
            return Response(data, status=status.HTTP_404_NOT_FOUND)
    else:
        logger.exception(exc)
        if hasattr(exc, "message"):
            msg = str(exc.message)
        else:
            msg = str(exc)
        data = error_message(code=SERVICE_ERROR, msg=msg, msg_show="服务端异常")
        return Response(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class MessageResponse(Response):
    """统一响应"""
    def __init__(self,
                 msg,
                 msg_show=None,
                 code=INFO_CODE,
                 bean=None,
                 list=None,
                 **kwargs):
        """
        :param msg: 响应信息(中文)
        :param msg_show: 响应信息(英文)
        :param code: 业务状态码
        :param bean: 对象信息
        :param list: 列表信息
        :param kwargs:
        """
        response_key = {
            "template_name", "headers", "exception", "content_type"
        }
        body_kwargs = {
            k: v
            for k, v in kwargs.items() if k not in response_key
        }
        response_kwargs = {
            k: v
            for k, v in kwargs.items() if k in response_key
        }
        body = {
            "code": code,
            "msg": msg,
            "msg_show": msg_show or msg,
            "data": dict(bean=bean or {}, list=list or [], **body_kwargs)
        }
        str_code = str(code)
        status_code = 200
        if str_code.startswith('104'):
            status_code = 400
        elif code == AUTHENTICATION_ERROR:
            status_code = 401
        elif code == PERMISSIONE_RROR:
            status_code = 403
        elif str_code.startswith('105'):
            status_code = 500
        super(MessageResponse, self).__init__(data=body,
                                              status=status_code,
                                              **response_kwargs)


class OpenApiMessageResponse(Response):
    """统一响应"""
    def __init__(self, msg, msg_show=None, code=INFO_CODE, **kwargs):
        """
        :param msg: 响应信息(中文)
        :param msg_show: 响应信息(英文)
        :param code: 业务状态码
        :param bean: 对象信息
        :param list: 列表信息
        :param kwargs:
        """
        response_key = {
            "template_name", "headers", "exception", "content_type"
        }
        body_kwargs = {
            k: v
            for k, v in kwargs.items() if k not in response_key
        }
        response_kwargs = {
            k: v
            for k, v in kwargs.items() if k in response_key
        }
        body = {
            "code": code,
            "msg": msg,
            "msg_show": msg_show or msg,
            **body_kwargs
        }
        super(OpenApiMessageResponse, self).__init__(data=body,
                                                     status=200,
                                                     **response_kwargs)


class ServiceHandleException(Exception):
    def __init__(self, msg, code, msg_show=None):
        """
        :param msg: 错误信息(英文)
        :param msg_show: 错误信息(中文)
        :param code: 业务码
        """
        super(Exception, self).__init__(code, msg, msg_show)
        self.code = code
        self.msg = msg
        self.msg_show = msg_show or self.msg

    @property
    def response(self):
        return MessageResponse(code=self.code,
                               msg=self.msg,
                               msg_show=self.msg_show)


class OpenApiServiceHandleException(Exception):
    def __init__(self, msg, code, msg_show=None):
        """
        :param msg: 错误信息(英文)
        :param msg_show: 错误信息(中文)
        :param code: 业务码
        """
        super(Exception, self).__init__(code, msg, msg_show)
        self.code = code
        self.msg = msg
        self.msg_show = msg_show or self.msg

    @property
    def response(self):
        return OpenApiMessageResponse(code=self.code,
                                      msg=self.msg,
                                      msg_show=self.msg_show)


class AuthenticationError(ServiceHandleException):
    def __init__(self, msg_show):
        super(AuthenticationError, self).__init__("authentication error",
                                                  msg_show=msg_show,
                                                  code=AUTHENTICATION_ERROR)


class UserNotFound(ServiceHandleException):
    def __init__(self):
        super(UserNotFound, self).__init__("user not found",
                                           msg_show="用户不存在",
                                           code=USER_NOT_FOUND)


class PasswordWrong(ServiceHandleException):
    def __init__(self):
        super(PasswordWrong, self).__init__("password wrong",
                                            msg_show="密码错误",
                                            code=PASSWORD_WRONG)


class ValidationError(ServiceHandleException):
    def __init__(self, msg_show):
        super(ValidationError, self).__init__("validate error",
                                              msg_show=msg_show,
                                              code=VERIFICATION_ERROR)


class NoPermissionError(ServiceHandleException):
    def __init__(self, msg_show=None):
        if not msg_show:
            msg_show = "无操作权限"
        super(NoPermissionError, self).__init__("no permission",
                                                msg_show=msg_show,
                                                code=PERMISSIONE_RROR)


class TooManyLinesRecv(ServiceHandleException):
    def __init__(self, msg_show=None):
        if not msg_show:
            msg_show = "返回数据超过阈值，请批量查询或丰富模糊查询内容"
        super(TooManyLinesRecv, self).__init__("too many lines recv",
                                               msg_show=msg_show,
                                               code=TOO_MANY_LINES)


class SearchNoFound(ServiceHandleException):
    def __init__(self, msg_show=None):
        if not msg_show:
            msg_show = "没有查到相关内容"
        super(SearchNoFound, self).__init__("search no found",
                                            msg_show=msg_show,
                                            code=SEARCH_NO_FOUND)


class NetWorkError(ServiceHandleException):
    def __init__(self, msg_show=None):
        if not msg_show:
            msg_show = "操作失败，请检查您的网络"
        super(NetWorkError, self).__init__("search no found",
                                           msg_show=msg_show,
                                           code=NETWORK_ERROR)


class ApiException(ServiceHandleException):
    def __init__(self, msg=None, msg_show=None):
        if not msg_show:
            msg_show = "接口调用失败，请检查您的网络"
        if not msg:
            msg = "call api error"
        super(ApiException, self).__init__(msg,
                                           msg_show=msg_show,
                                           code=THIRD_PARTY_API_ERROR)


class ApiAuthenticationError(Exception):
    def __init__(self, *args, **kwargs):
        pass
