/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.common.web.exception;

import com.crunii.micro.common.dto.Result;
import com.crunii.micro.common.exception.BusinessException;
import com.crunii.micro.common.exception.MicroException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * @author 田平 create 2018年10月16日上午9:25:03
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

	@ExceptionHandler(Exception.class)
	public ResponseEntity<Result<String>> defaultExceptionHandler(HttpServletRequest request, Exception e) {
		log.error("request url:{}", request.getRequestURI(), e);
		Result<String> result = new Result<String>();
		result.setCode(Result.DEFAULT_ERROR_CODE);
		result.setSuccess(false);
		result.setMsg("内部错误！");
		return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
	}

	@ExceptionHandler(BusinessException.class)
	@ResponseBody
	public ResponseEntity<Result<String>> businessExceptionHandler(HttpServletRequest request, HttpServletResponse response, BusinessException e) {
		log.error("request url:{}", request.getRequestURI(), e);
		Result<String> result = new Result<String>();
		result.setCode(Result.DEFAULT_ERROR_CODE);
		result.setSuccess(false);
		result.setMsg(e.getMessage());
		return ResponseEntity.status(HttpStatus.OK).body(result);
	}

	@ExceptionHandler(IllegalArgumentException.class)
	@ResponseBody
	public ResponseEntity<Result<String>> IllegalArgumentExceptionHandler(HttpServletRequest request, HttpServletResponse response, IllegalArgumentException e) {
		log.error("request url:{}", request.getRequestURI(), e);
		Result<String> result = new Result<String>();
		result.setCode(Result.DEFAULT_ERROR_CODE);
		result.setSuccess(false);
		result.setMsg(e.getMessage());
		return ResponseEntity.status(HttpStatus.OK).body(result);
	}

	@ExceptionHandler(MethodArgumentNotValidException.class)
	@ResponseBody
	public ResponseEntity<Result<String>> methodArgumentNotValidExceptionHandler(HttpServletRequest request, HttpServletResponse response, MethodArgumentNotValidException e) {
		log.error("request url:{}", request.getRequestURI(), e);
		BindingResult bindingResult = e.getBindingResult();
		StringBuilder errorMsg = new StringBuilder();
		for (int i = 0; i < bindingResult.getFieldErrors().size(); ++i) {
			if (i > 0) {
				errorMsg.append(", ");
			}
			FieldError fe = bindingResult.getFieldErrors().get(i);
			errorMsg.append(fe.getDefaultMessage());
		}
		Result<String> result = new Result<>();
		result.setCode(Result.DEFAULT_ERROR_CODE);
		result.setSuccess(false);
		result.setMsg(errorMsg.toString());
		return ResponseEntity.status(HttpStatus.OK).body(result);
	}

	@ExceptionHandler(ConstraintViolationException.class)
	@ResponseBody
	public ResponseEntity<Result<String>> constraintViolationExceptionHandler(HttpServletRequest request, HttpServletResponse response, ConstraintViolationException e) {
		log.error("request url:{}", request.getRequestURI(), e);
		StringBuilder errorMsg = new StringBuilder();
		Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
		for (ConstraintViolation<?> violation : violations) {
			String path = violation.getPropertyPath().toString();
			String field = path.substring(path.lastIndexOf(".") + 1);
			errorMsg.append(violation.getMessage());
			break;
		}
		Result<String> result = new Result<String>();
		result.setCode(Result.DEFAULT_ERROR_CODE);
		result.setSuccess(false);
		result.setMsg(errorMsg.toString());
		return ResponseEntity.status(HttpStatus.OK).body(result);
	}

	@ExceptionHandler(MicroException.class)
	@ResponseBody
	public ResponseEntity<Result<String>> microExceptionHandler(HttpServletRequest request, HttpServletResponse response, MicroException e) {
		log.error("request url:{}", request.getRequestURI(), e);
		Result<String> result = new Result<String>();
		result.setCode(e.getCode());
		result.setSuccess(false);
		result.setMsg(e.getMessage());
		return ResponseEntity.status(HttpStatus.OK).body(result);
	}

}
