package cn.component.exception;

import cn.common.enums.ResultCode;
import cn.common.exception.BaseException;
import cn.common.exception.SecurityException;
import cn.common.page.response.Result;
import cn.util.core.IsKit;
import cn.util.core.LogKit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.connection.PoolException;
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.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
/**
 * @ControllerAdvice + @ExceptionHand 配置全局异常处理类
 * 
 * 类描述: 全局异常拦截处理器
 * 前端异常处理(axios拦截器)
 */
@RestControllerAdvice
public class GlobalExceptionHandler 
{
	/**拒绝访问异常处理(AccessDeniedException)_spring security */
	@ExceptionHandler(AccessDeniedException.class) 
	public Result<?> handleAccessDeniedException(AccessDeniedException e, 
			HttpServletRequest request, HttpServletResponse response) throws Exception
	{ 
		LogKit.error("访问操作被拒绝:", e.getMessage());
		return Result.warnMsg(ResultCode.USER_UNAUTHORIZED.getMsg());
	} 
	/**
	 * 处理 Exception 异常 */
	@ExceptionHandler(value = Exception.class)//声明需要捕获的异常类
	public Result<?> handleException(Exception e) {
		LogKit.error("异常类捕获:" + e.getClass());
		if( IsKit.isNotNull(e.getCause()) && e.getCause().toString().contains("java.sql.SQL") ){
            return Result.warnMsg("数据库操作失败:"+e.getMessage());
        }else{
            return Result.warnMsg(ResultCode.SYS_SERVER.getMsg());
        }
	}
	/**
	 * 处理自定义异常  RuntimeException
	 * @ExceptionHandler(RuntimeException.class)
	 * Result<?>
	 */
	@ExceptionHandler(BaseException.class)
	public Result<?> handleRRException(BaseException e) 
	{
		LogKit.info(e.getModule() + ": " + e.getMessage());
		return Result.warnMsg(ResultCode.SYS_SERVER.getMsg());
	}
	/**
	 * 业务异常
	 */
	@ExceptionHandler(SecurityException.class)
	public Result<?> businessException(SecurityException e) {
		LogKit.info(e.getCode() + ": " + e.getMessage());
		if (IsKit.isNull(e.getCode())) {
			return Result.warnMsg(e.getMessage());
		}
		return Result.warnMsg(e.getMessage());
	}
	/**
	 * Redis 连接异常
	 */
	@ExceptionHandler(PoolException.class)
	public Result<?> handlePoolException(PoolException e) {
		LogKit.error("Redis 连接异常!",e.getMessage());
		return Result.warnMsg(ResultCode.SYS_REDIS_CONNECT.getMsg());
	}

	/**
	 * 路径不存在异常
	 */
	@ExceptionHandler(NoHandlerFoundException.class)
	public Result<?> handlerNoFoundException(Exception e) {
		LogKit.error("路径不存在，请检查路径是否正确",e.getMessage());
		return Result.warnMsg(ResultCode.SYS_RESOURSE_NOT_FOUND.getMsg());
	}

	/**
	 * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
	 */
	@ExceptionHandler(MaxUploadSizeExceededException.class)
	public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
		LogKit.error("文件大小超出10MB限制, 请压缩或降低文件质量! ",e.getMessage());
		return Result.warnMsg(ResultCode.FILE_OVARSIZE.getMsg());

	}

	/**
	 * 段太长,超出数据库字段的长度
	 */
	@ExceptionHandler(DataIntegrityViolationException.class)
	public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
		LogKit.error("字段太长,超出数据库字段的长度",e.getMessage());
		return Result.warnMsg(ResultCode.DATA_TOO_LENGTH.getMsg());
	}
	/**
	 * 拦截抛出的异常，@ResponseStatus：用来改变响应状态码
	 */
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	@ExceptionHandler(Throwable.class)
	public Result<?> handlerThrowable(Throwable e, HttpServletRequest request) {
		LogKit.error("发生未知异常！原因是: ", e);
		return Result.warnMsg(ResultCode.HTTP_INTERNAL_SERVER_ERROR.getMsg());
	}

	/** 处理400类异常 */
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ExceptionHandler(ConstraintViolationException.class)
	public Result<?> handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
		return Result.warnMsg(ResultCode.HTTP_BAD_REQUEST.getMsg());
	}

	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ExceptionHandler(HttpMessageNotReadableException.class)
	public Result<?> handleConstraintViolationException(HttpMessageNotReadableException e, HttpServletRequest request) {
		return Result.warnMsg(ResultCode.HTTP_BAD_REQUEST.getMsg());
	}

	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ExceptionHandler(BindException.class)
	public Result<?> handleBindException(BindException e, HttpServletRequest request) {
		return Result.warnMsg(ResultCode.HTTP_BAD_REQUEST.getMsg());
	}

	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public Result<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
		LogKit.error("发生参数校验异常！原因是：", e);
		return Result.warnMsg(ResultCode.HTTP_BAD_REQUEST.getMsg());
	}
}
