package com.yiboshi.science.config.exception;

import com.yiboshi.arch.base.ResponseCode;
import com.yiboshi.arch.base.ResponseDataModel;
import com.yiboshi.arch.exception.BusinessException;
import com.yiboshi.science.service.LogsExceptionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;

/**
 * class: GlobalExceptionHandler(全局异常处理)
 * create by: dracula$
 * description:
 * create time: 2021-09-13$
 *
 * @param: $
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private LogsExceptionService logsExceptionService;

    /**
     * 全局未知异常处理
     *
     * @param request
     * @param handlerMethod
     * @param exception
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseDataModel handleException(HttpServletRequest request, HandlerMethod handlerMethod, Exception exception) {//HttpServletResponse response,
        return AllExceptionHandler(request, handlerMethod, exception);
    }

    /**
     * BadCredentialsException
     */
    @ExceptionHandler(BadCredentialsException.class)
    public ResponseDataModel badCredentialsException(HttpServletRequest request, HandlerMethod handlerMethod, Exception e) {
        // 打印堆栈信息
        String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage();
        return AllExceptionHandler(request, handlerMethod, e);
    }

    /**
     * 处理所有业务异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public ResponseDataModel handleBusinessException(HttpServletRequest request, HandlerMethod handlerMethod, BusinessException exception) {
        return AllExceptionHandler(request, handlerMethod, exception);
    }

    /**
     * 处理所有接口数据验证异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseDataModel handleMethodArgumentNotValidException(HttpServletRequest request, HandlerMethod handlerMethod, MethodArgumentNotValidException exception) {
        return AllExceptionHandler(request, handlerMethod, exception);
    }

    /**
     * 异常分类处理
     *
     * @param request
     * @param handlerMethod
     * @param exception
     * @return
     */
    private ResponseDataModel AllExceptionHandler(HttpServletRequest request, HandlerMethod handlerMethod, Exception exception) {
        String msg;
        ResponseCode responseCode=ResponseCode.BUSSINESS_EXCEPTION;
        if (exception instanceof BusinessException) {
            msg = exception.getMessage();
        } else if (exception instanceof BadCredentialsException) {
            msg = "用户名或密码不正确";
        } else if (exception instanceof InvalidGrantException) {
            msg = "用户名或密码不正确";
        } else if (exception instanceof UsernameNotFoundException) {
            msg = "用户名或密码不正确";
        } else if (exception instanceof InternalAuthenticationServiceException) {
            msg = "账户不存在或已注销！";
        } else if (exception instanceof DisabledException) {
            msg = "账户不存在或已注销！";
        } else if (exception instanceof AccessDeniedException) {
            msg = "无权限访问";
        } else if (exception instanceof MethodArgumentNotValidException) {
            msg = "接口数据验证异常";
            responseCode=ResponseCode.PARAMETER_EXCEPTION;
            logsExceptionService.logs(handlerMethod,exception,"接口数据验证异常");
        } else{
            msg = exception.getMessage();
            responseCode=ResponseCode.SERVER_ERROR;
            logsExceptionService.logs(handlerMethod,exception,"500 Internal Server Error！");
        }
        return new ResponseDataModel(responseCode, msg);
    }

    /**
     * 区分业务类和方法
     *
     * @param request
     * @param handlerMethod
     * @return
     * @throws Exception
     */
    private String decisionShortTitle(HttpServletRequest request, HandlerMethod handlerMethod) {
        String className = handlerMethod.getMethod().getDeclaringClass().getName();
        String MethodType = request.getMethod();
        String MethodName = handlerMethod.getMethod().getName();
        return className + ":" + MethodName + ":" + MethodType;
    }

}

