package com.hzya.frame.webapp.web.exception;


import cn.dev33.satoken.exception.NotLoginException;
import com.hzya.frame.web.entity.BaseResult;
import com.hzya.frame.web.entity.JsonResultEntity;
import com.hzya.frame.web.exception.BaseSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
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.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;

/**
 * @Content所有controller抛出的异常，统一此处处理
 * @Author 👻👻👻👻👻👻👻👻👻👻 gjh
 * @Date 2022-12-06 9:37
 * @Version 1.0
 */
@ControllerAdvice
public class ExceptionController {

    private final static Logger LOGGER = LoggerFactory.getLogger(ExceptionController.class);

//    @Autowired
//    private ExceptionLogService exceptionLogService;

    @ExceptionHandler(value = NoHandlerFoundException.class)
    public ModelAndView notHandlerFoundExceptionHandler(HttpServletRequest request, Exception e) {
        LOGGER.error(e.getMessage(), e);
        return new ModelAndView("redirect:/common/404");
    }

    @ExceptionHandler(value = BaseSystemException.class)
    @ResponseBody
    public JsonResultEntity exceptionHandle(HttpServletRequest request, BaseSystemException baseSystemException) {
        HttpStatus httpStatus = getStatus(request);
        Integer statusCode = httpStatus.value();
        baseSystemException.printStackTrace();
        LOGGER.error(baseSystemException.getMessage());

        String message = baseSystemException.getMessage();
        String data = baseSystemException.getLocalizedMessage();
        return getErrorJsonResultEntity(message,data, httpStatus, statusCode);
    }

    @ExceptionHandler(NotLoginException.class)
    @ResponseBody
    public JsonResultEntity exceptionHandle(HttpServletRequest request, NotLoginException notLoginException) {
        HttpStatus httpStatus = getStatus(request);
        Integer statusCode = httpStatus.value();
        notLoginException.printStackTrace();
        LOGGER.error(notLoginException.getMessage());
        String message = notLoginException.getMessage();
        // 判断场景值，定制化异常信息
        if (notLoginException.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = "未提供token";
        } else if (notLoginException.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = "zt-token无效";
        } else if (notLoginException.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = "zt-token已过期";
        } else if (notLoginException.getType().equals(NotLoginException.BE_REPLACED)) {
            message = "zt-token已被顶下线";
        } else if (notLoginException.getType().equals(NotLoginException.KICK_OUT)) {
            message = "zt-token已被踢下线";
        } else {
            message = "当前会话未登录";
        }
        String data = notLoginException.getLocalizedMessage();
        return getErrorJsonResultEntity(message,data, httpStatus, statusCode);
    }
    private JsonResultEntity getErrorJsonResultEntity(String message, String data, HttpStatus httpStatus, Integer statusCode) {

        switch (statusCode){
            case 403:
                message = "没有权限";
                data = "/common/403";
                break;
            case 404:
                message = "未找到请求路径";
                data = "/common/404";
                break;
            case 500:
                message = message == null ? "系统错误，请联系管理员" : message;
                data = "/common/500";
                break;
            default:

        }


        return BaseResult.getFailureMessageEntity(message, String.valueOf(httpStatus.value()), data );
    }


    /***
     * @Content:监听系统异常
     * @Author 👻👻👻👻👻👻👻👻 gjh
     * @Date 2022-12-06 11:40
     * @Param [request, e]
     * @return org.springframework.web.servlet.ModelAndView
     **/
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public JsonResultEntity exceptionHandle(HttpServletRequest request, Exception exception) {
        // 输出异常日志
        exception.printStackTrace();
        //获取状态码
        HttpStatus httpStatus = getStatus(  request);
        Integer statusCode = httpStatus.value();
        // 构建返回数据
        String message = exception.getMessage();
        String data = exception.getLocalizedMessage();
        LOGGER.info("系统错误!",exception);
        return getErrorJsonResultEntity(message,data, httpStatus, statusCode);
 }

    private boolean isInterface(HttpServletRequest request) {
        // 通过debug调试可以看出request中含有该对象。
        HandlerMethod handlerMethod = (HandlerMethod) request.getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingHandler");
        // getBeanType()拿到发送请求得类模板（Class），getDeclaredAnnotationsByType(指定注解类模板)通过指定得注解，得到一个数组。
        if (null != handlerMethod) {
            RestController[] annotations1 = handlerMethod.getBeanType().getDeclaredAnnotationsByType(RestController.class);
            ResponseBody[] annotations2 = handlerMethod.getBeanType().getDeclaredAnnotationsByType(ResponseBody.class);
            ResponseBody[] annotations3 = handlerMethod.getMethod().getAnnotationsByType(ResponseBody.class);
            // 判断当类上含有@RestController或是@ResponseBody或是方法上有@ResponseBody时，则表明该异常是一个接口请求发生的
            return annotations1.length > 0 || annotations2.length > 0 || annotations3.length > 0;
        } else {
            return false;
        }

    }


    protected HttpStatus getStatus(HttpServletRequest request) {
        // 获取状态值
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        } else {
            try {
                return HttpStatus.valueOf(statusCode);
            } catch (Exception var4) {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }
        }
    }
}


