package com.yeejoin.precontrol.common.exception.handle;

import com.github.liangbaika.validate.exception.ParamsInValidException;
import com.yeejoin.precontrol.common.exception.BaseException;

import lombok.extern.slf4j.Slf4j;

import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @description: 全局异常处理器
 * @author: duanwei
 * @create: 2019-08-28 20:07
 **/
@RestControllerAdvice(value="GlobalExceptionHandler")
@Slf4j
@Primary
@Component(value = "GlobalExceptionHandler")
public class GlobalExceptionHandler {

	/**
	 * 校验异常统一拦截地方
	 * 
	 * @param e
	 * @return
	 */
	@ExceptionHandler({ ParamsInValidException.class, MethodArgumentNotValidException.class, BindException.class })
	@ResponseBody
	public ResponseModel<Object> handleParamsValidException(Exception e) {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		ResponseModel<Object> response = new ResponseModel<>();
		response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
		response.setTraceId(RequestContext.getTraceId());
		response.setPath(request.getServletPath());
		if (e instanceof ParamsInValidException) {
			response.setDevMessage(e.getMessage());
			response.setMessage(e.getMessage());
		} else {
			BindingResult bindingResult = null;
			if (e instanceof BindException) {
				bindingResult = ((BindException) e).getBindingResult();
			} else {
				bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
			}
			StringBuilder errMsg = getErrorInfo(bindingResult);
			response.setDevMessage(errMsg.toString());
			response.setMessage(errMsg.toString());
		}
		return response;
	}

	/**
	 * 其他异常拦截
	 * 
	 * @param exception
	 * @return
	 */
	@ExceptionHandler({ Exception.class })
	public ResponseModel<Object> methodArgumentNotValidHandler(Exception exception) {
		ResponseModel<Object> response = new ResponseModel<>();
		if (exception instanceof MaxUploadSizeExceededException) {
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getRequest();
			response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
			response.setDevMessage("上传文件过大[单个文件大小不得超过10M]");
			response.setMessage(exception.getMessage());
			response.setTraceId(RequestContext.getTraceId());
			response.setPath(request.getServletPath());
		} else {
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getRequest();
			response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
			response.setDevMessage(exception.getMessage());
			response.setMessage(exception.getMessage());
			response.setTraceId(RequestContext.getTraceId());
			response.setPath(request.getServletPath());
		}
		if (exception instanceof BaseException) {
			if (((BaseException) exception).getCode() == 1) {
				log.error(exception.getMessage());
			} else {
				log.error(exception.getMessage(), exception);
			}
		} else {
			log.error(exception.getMessage(), exception);
		}
		return response;
	}

	private StringBuilder getErrorInfo(BindingResult bindingResult) {
		List<ObjectError> allErrors = bindingResult.getAllErrors();
		StringBuilder errMsg = new StringBuilder();
		for (ObjectError allError : allErrors) {
			FieldError fieldError = (FieldError) allError;
			String field = fieldError.getField();
			String defaultMessage = fieldError.getDefaultMessage();
			errMsg.append(field + ":" + defaultMessage + ";  ");
		}
		return errMsg;
	}

}