package com.jwipc.web;

import cn.dev33.satoken.exception.NotLoginException;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.exception.ParamCheckException;
import com.jwipc.exception.error.BaseErrorCode;
import com.jwipc.exception.error.ErrorModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
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 org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;

/**
 * <p> 全局异常处理 </p>
 *
 * @author sog
 * @version 1.0
 * @since JDK 1.7
 */
@ControllerAdvice
public class GlobalExceptionHandler {


    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);


    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = ParamCheckException.class)
    @ResponseBody
    public ErrorModel paramCheckException(ParamCheckException e)
            throws Exception
    {
        logger.error("The param check handle exception!", e);
        final String message = e.getMessage();
        return ErrorModel.builder().setCode(e.getCode())
                .setMessage(message).createErrorModel();
    }


    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Object handleException(Exception e) {
        logger.error("The handle exception!", e);
        final HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        final HttpServletResponse response =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        String requestedWithHeader = request.getHeader("X-Requested-With");
        if ("XMLHttpRequest".equals(requestedWithHeader)) {
            return ErrorModel.builder()
                    .setCode(BaseErrorCode.ERRROR)
                    .setMessage(e.getMessage())
                    .createErrorModel();
        } else {
            return new ModelAndView("redirect:" + "/errorPage");
        }

    }

    @ExceptionHandler(NotLoginException.class)
    public ModelAndView handleNotLoginException(NotLoginException ex) {
        final HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        final HttpServletResponse response =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        String requestedWithHeader = request.getHeader("X-Requested-With");
        if ("XMLHttpRequest".equals(requestedWithHeader)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return new ModelAndView();
        } else {
            return new ModelAndView("redirect:" + "/login");
        }
    }

    /**
     * API接口参数验证异常
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    @ResponseBody
    public ApiResult handleValidatedException(Exception e) {
        e.printStackTrace();
        if (e instanceof  MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex =(MethodArgumentNotValidException)  e;
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(ex.getFieldError().getDefaultMessage()).build();
        } else  if (e instanceof ConstraintViolationException){
            ConstraintViolationException ex = (ConstraintViolationException) e;
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(ex.getMessage()).build();
        }else  if (e instanceof BindException) {
            BindException  ex = (BindException ) e;
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("Params Error").build();
        }
        return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("System Error").build();
    }
}
