package com.common.exception;

import com.alibaba.fastjson.JSONException;
import com.common.utils.LogUtils;
import com.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

@Slf4j
@RestControllerAdvice
public class RRExceptionHandler {
    @Autowired
    private LogUtils logUtils;
    /**
     * 处理自定义异常
     */
    @ExceptionHandler(RRException.class)
    public R handleRRException(RRException e){
        R r;
//        if (StringUtils.isEmpty(e.getMessage())) {
//            r = R.error();
//        }
        r = R.error(e.getErrno(), e.getErrmsg());
        logUtils.requestLog(r);
        return r;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public R handlerMyNoHandlerFoundException(NoHandlerFoundException e) {
        R r = R.error("404", "路径不存在，请检查路径是否正确");
        logUtils.requestLog(r);
        return r;
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public R handleDuplicateKeyException(DuplicateKeyException e){
        logUtils.requestLog(e);
        return R.error("数据库中已存在该记录");
    }

//    @ExceptionHandler(AuthorizationException.class)
//    public R handleAuthorizationException(AuthorizationException e){
//        R r = R.error("没有权限，请联系管理员授权");
//        logUtils.requestLog(r);
//        return r;
//    }

    /**
     * 处理 @Valid 对 @RequestBody 参数验证异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        FieldError fieldError = e.getBindingResult().getFieldError();
        R r = R.error(fieldError.getField() + fieldError.getDefaultMessage());
        logUtils.requestLog(r);
        return r;
    }

    /**
     * 参数类型转换错误
     *
     * @param exception 错误
     * @return 错误信息
     */
    @ExceptionHandler(HttpMessageConversionException.class)
    public R parameterTypeException(HttpMessageConversionException exception) {
        R r = R.error(exception.getCause().getLocalizedMessage());
        return  r;
    }

    /**
     * 处理 @RequestBody 但 body none 异常
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        String message = e.getMessage();
        R r = R.error(message.substring(0, message.indexOf(":")));
        logUtils.requestLog(message);
        return r;
    }

    /**
     * 处理 @RequestParam required=true 但未收到值异常
     * @param e
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public R handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        R r = R.error("缺少参数" + e.getParameterName());
        logUtils.requestLog(r);
        return r;
    }

    @ExceptionHandler(JSONException.class)
    public R handleJSONException(JSONException e){
//        logUtils.requestLog(e);
        return R.error("数据格式错误");
    }

    /**
     * 处理请求方法不支持异常
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        R r = R.error(String.format("当前路径不支持%s请求", e.getMethod()));
        logUtils.requestLog(r);
        return r;
    }

    @ExceptionHandler(Exception.class)
    public R handleException(Exception e){
        logUtils.requestLog(e);
        e.printStackTrace();
        return R.error();
    }
}
