package cn.hanghui.outapi.platform.common.interceptor;

import cn.hanghui.outapi.platform.common.entity.rest.RestResponse;
import cn.hanghui.outapi.platform.common.entity.rest.RestResult;
import cn.hanghui.outapi.platform.common.entity.rest.Result;
import cn.hanghui.outapi.platform.common.exception.BusinessException;
import cn.hanghui.outapi.platform.common.exception.CommonException;
import cn.hutool.core.util.ObjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.Objects;

@RestControllerAdvice
public class ExceptionInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(ExceptionInterceptor.class);

    /**
     * 通用异常拦截器
     */
    @ExceptionHandler(CommonException.class)
    public Result<?> exceptionHandler(CommonException e) {
        logger.error(e.getErrMsg(), e);
        Exception sysException = e.getSysException();
        if (ObjectUtil.isNotNull(sysException)) {
            logger.error(sysException.toString());
            for (StackTraceElement stackTraceElement : sysException.getStackTrace()) {
                logger.error(stackTraceElement.toString());
            }

        }
        return Result.error(e);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<?> constraintViolationException(ConstraintViolationException e) {
        logger.error(e.getMessage(), e);
        String message = e.getConstraintViolations().iterator().next().getMessage();
        return Result.error(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        logger.error(e.getMessage(), e);
        String message = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
        return Result.error(message);
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(RuntimeException.class)
    public Result<?> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        logger.error("请求地址'{}',发生未知异常.", requestUri, e);
        return Result.error();
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public Result<?> handleException(Exception e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        logger.error("请求地址'{}',发生未知异常.", requestUri, e);
        return Result.error();
    }

    /**
     * 通用业务异常拦截器
     */
    @ExceptionHandler(BusinessException.class)
    public RestResult<?> businessExceptionHandler(BusinessException e) {
        logger.error(e.getMsg(), e);
        Exception sysException = e.getSysException();
        if (ObjectUtil.isNotNull(sysException)) {
            logger.error(sysException.toString());
            for (StackTraceElement stackTraceElement : sysException.getStackTrace()) {
                logger.error(stackTraceElement.toString());
            }

        }
        return RestResponse.build(e.getCode(), e.getMsg());
    }

}
