package org.shunt.aop;

import java.util.List;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolationException;
import javax.validation.Path;

import org.shunt.common.XmoseResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;

import lombok.extern.slf4j.Slf4j;

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public XmoseResponse<String> handleValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField()+fieldError.getDefaultMessage();
            }
            log.error(message);
        }
        return XmoseResponse.fail(XmoseResponse.CODE_UNSUPPORTED, "参数错误");
    }

    @ResponseBody
    @ExceptionHandler(value = JsonMappingException.class)
    public XmoseResponse<String> handleInvalidFormatException(JsonMappingException e) {
        log.error(e.getOriginalMessage());
        return XmoseResponse.fail(XmoseResponse.CODE_UNSUPPORTED, "参数格式错误");
    }

    @ResponseBody
    @ExceptionHandler(value = JsonParseException.class)
    public XmoseResponse<String> handleJsonParseException(JsonParseException e) {
        log.error(e.getOriginalMessage());
        return XmoseResponse.fail(XmoseResponse.CODE_UNSUPPORTED, "参数Json格式错误");
    }

    @ResponseBody
    @ExceptionHandler(value = BindException.class)
    public XmoseResponse<String> handleValidException(BindException e) {
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField()+fieldError.getDefaultMessage();
            }
            log.error(message, e);
        }
        return XmoseResponse.fail(XmoseResponse.CODE_UNSUPPORTED, "参数绑定错误");
    }

    @ResponseBody
    @ExceptionHandler(value = ConstraintViolationException.class)
    public XmoseResponse<List<String>> handleValidException(ConstraintViolationException e) {
        List<String> messages = e.getConstraintViolations().stream().map(violation -> {
            //node是路径最后一个节点,即参数名
            Path.Node lastNode = null;
            for (Path.Node node : violation.getPropertyPath()) {
                lastNode = node;
            }
            return lastNode.getName() + violation.getMessage();
        }).collect(Collectors.toList());
        log.error(messages.isEmpty() ? "" : messages.get(0));
        return XmoseResponse.fail(XmoseResponse.CODE_UNSUPPORTED, "参数绑定错误");
    }


}
