package com.persagy.dmp.common.handler;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.persagy.dmp.common.constant.ResponseCode;
import com.persagy.dmp.common.exception.BusinessException;
import com.persagy.dmp.common.model.response.CommonResult;
import com.persagy.dmp.common.utils.ResultHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.security.auth.message.AuthException;
import javax.validation.ValidationException;
import java.sql.SQLException;

/**
 * @description: 通用异常处理类
 * @author: lixing
 * @since: 2021/3/5 5:10 下午
 **/
@RestControllerAdvice
@Slf4j
public class CommonExceptionHandler {

    /**
     * 空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    public CommonResult handleBusinessRuntimeException(NullPointerException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.B0001.getCode(), ExceptionUtil.getRootCauseMessage(e));
    }

    /**
     * 自定义业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public CommonResult handleBusinessRuntimeException(BusinessException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(e.getErrorCode(), e.getErrorDesc());
    }

    /**
     * SQL异常
     * @param e
     * @return
     */
    @ExceptionHandler(SQLException.class)
    public CommonResult handleSqlException(SQLException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0400.getCode(), e.getMessage());
    }

    /**
     * 入参校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0400.getCode(), e.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * 入参校验异常
     */
    @ExceptionHandler(BindException.class)
    public CommonResult handleBindException(BindException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0400.getCode(), e.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * 参数校验异常，message 为手动抛出时定义的具体异常信息
     */
    @ExceptionHandler(ValidationException.class)
    public CommonResult handleValidationException(ValidationException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0400.getCode(), e.getCause().getMessage());
    }

    /**
     * 参数校验异常，message 为手动抛出时定义的具体异常信息
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public CommonResult handleIllegalArgumentException(IllegalArgumentException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0400.getCode(), e.getMessage());
    }

    /**
     * URI请求链接没有映射
     */
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public CommonResult handleNoHandlerFoundException(NoHandlerFoundException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0422.getCode(), e.getMessage());
    }

    /**
     *  body体未找到
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public CommonResult handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0402.getCode(), ResponseCode.A0402.getDesc());
    }

    /**
     *  body体未找到
     */
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(AuthException.class)
    public CommonResult handlerAuthException(AuthException e) {
        log.error(e.getMessage(), e);
        return ResultHelper.failure(ResponseCode.A0220.getCode(), ResponseCode.A0220.getDesc());
    }

    /**
     * 系统默认繁忙
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public CommonResult handleException(Exception e) {
        log.error(e.getMessage(), e);
        // 20210819 返回实际的异常信息
        return ResultHelper.failure(ResponseCode.Z9999.getCode(), ExceptionUtil.getRootCauseMessage(e));
    }
}
