package com.gonghang.h5clientapp.exception;

import com.gonghang.h5clientapp.common.ResultData;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description: 自定义异常处理
 * @Author: shiwn
 * @Date: 2020/1/17 11:19
 */
@RestController
@ControllerAdvice
public class ControllerAdviceHandle {

    /**
     * @Description: 处理自定义异常
     * @Param: [request, e]
     * @Author: shiwn
     * @Date: 2020/1/17 11:36
     */
    @ExceptionHandler({BusinessException.class})
    public ResultData businessExceptionHandler(BusinessException e) throws BusinessException {
        return ResultData.fail(e.getCode(), e.getMessage());
    }

    /**
     * @Description: 处理全局异常
     * @Param: [request, e]
     * @Author: shiwn
     * @Date: 2020/1/17 11:36
     */
    @ExceptionHandler(value = Exception.class)
    public ResultData handleException(Exception e) throws Exception {
        return ResultData.fail(e.getMessage());
    }


    // 新增如下代码:[捕获全局 参数校验异常 配合Valid使用]

    /**
     * 处理所有校验失败的异常（MethodArgumentNotValidException异常）
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultData handleBindGetException(MethodArgumentNotValidException ex) {
        // 获取所有异常
        List<String> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(x -> x.getDefaultMessage())
                .collect(Collectors.toList());
        return ResultData.fail(1, String.join(",", errors));
    }

    /**
     * 处理所有参数校验时抛出的异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = ValidationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultData handleBindException(ValidationException ex) {
        // 获取所有异常
        List<String> errors = new LinkedList<String>();
        if (ex instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) ex;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                errors.add(item.getMessage());
            }
        }
        return ResultData.fail(1, String.join(",", errors));
    }

    /**
     * Controller参数绑定错误
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResultData handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {
        return ResultData.fail(1, ex.getMessage());
    }
}
