package com.zanxiang.game.back.serve.handler;

import com.zanxiang.erp.security.exception.NoPermissionException;
import com.zanxiang.module.util.DateUtil;
import com.zanxiang.module.util.exception.BaseException;
import com.zanxiang.module.util.pojo.ResultVO;
import com.zanxiang.module.web.util.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.time.LocalDateTime;

/**
 * 全局异常代理
 *
 * @author bilingfeng
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 业务异常
     */
    @ExceptionHandler(BaseException.class)
    public ResultVO<?> baseException(BaseException e) {
        return ResultVO.fail(e.getMessage());
    }

    /**
     * http method错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultVO<?> methodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error("URL：{}, 请求 method：{}, 支持的 method：{}", ServletUtil.getRequest().getRequestURL(), ServletUtil.getRequest().getMethod(), e.getSupportedMethods());
        return ResultVO.fail("http method错误！");
    }

    /**
     * 自定义参数校验错误
     */
    @ExceptionHandler(BindException.class)
    public ResultVO<?> validatedBindException(BindException e) {
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return ResultVO.fail(message);
    }

    /**
     * 自定义参数校验错误
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultVO<?> validExceptionHandler(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return ResultVO.fail(message);
    }

    /**
     * 自定义参数校验错误
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResultVO<?> validExceptionHandler(HttpMessageNotReadableException e) {
        log.error(e.getMessage(), e);
        return ResultVO.fail("参数异常，请勿非法操作");
    }

    /**
     * 参数类型不匹配导致转换异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResultVO<?> mismatchErrorHandler(MethodArgumentTypeMismatchException e) {
        log.error("方法:{},字段:{},参数:{},错误信息:{}", e.getParameter().getMethod(), e.getName(), e.getValue(), e.getMessage());
        return ResultVO.fail("请求参数异常，请勿非法操作");
    }

    /**
     * 权限异常
     */
    @ExceptionHandler(NoPermissionException.class)
    public ResultVO<?> preAuthorizeException(NoPermissionException e) {
        return ResultVO.fail("没有权限，请联系管理员授权");
    }

    @ExceptionHandler(Exception.class)
    public ResultVO<?> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return ResultVO.fail(DateUtil.formatLocalDateTime(LocalDateTime.now()) + ": 服务异常，请联系管理员");
    }
}
