package com.energy.manage.service.config;

import com.alibaba.fastjson.JSONObject;
import com.energy.manage.common.exception.*;
import com.energy.manage.common.reponse.RespMsg;
import com.energy.manage.common.reponse.ResultResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.CrossOrigin;
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.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.io.IOException;
import java.util.Locale;
import java.util.stream.Collectors;


@RestControllerAdvice
@Slf4j
public class SystemExceptionHandler {

    @ExceptionHandler(value = ServiceErrorException.class)
    @ResponseBody
    @CrossOrigin
    public JSONObject doServiceErrorException() {
        return RespMsg.FAILException();
    }

    @ExceptionHandler(value = UserNotLoginException.class)
    @ResponseBody
    @CrossOrigin
    public JSONObject doUserNotLoginHandler() {
        return RespMsg.PLEASELOGIN();
    }

    @ExceptionHandler(value = TokenInvalidException.class)
    @ResponseBody
    @CrossOrigin
    public JSONObject doMorePersonLoginHandler() {
        return RespMsg.TOKENVALID();
    }

    @ExceptionHandler(value = ErrorSignException.class)
    @CrossOrigin
    @ResponseBody
    public JSONObject doErrorSign() {
        return RespMsg.ERRORSIGN();
    }

    @ExceptionHandler(value = NoRequestException.class)
    @CrossOrigin
    @ResponseBody
    public JSONObject doNoRequestHandler() {
        return RespMsg.NOREQUEST();
    }

    @ExceptionHandler(value = BusinessException.class)
    @CrossOrigin
    @ResponseBody
    public JSONObject serviceExceptionHandler(BusinessException businessException) {
        return RespMsg.FAIL(businessException.getCode(), businessException.getMessage());
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @CrossOrigin
    @ResponseBody
    public ResultResp methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException methodArgumentNotValidException) {
        return ResultResp.FAIL(methodArgumentNotValidException.getBindingResult().getFieldErrors().get(0).getDefaultMessage());
    }

    /**
     * 违反约束异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResultResp handConstraintViolationException(ConstraintViolationException e) {
        String msg = e.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.joining("; "));
        return ResultResp.FAIL(msg);
    }


    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public ResultResp validException(ValidationException exception) {
        return ResultResp.FAIL(exception.getMessage());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    protected ModelAndView handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
                                                               HttpServletRequest request, HttpServletResponse response,
                                                               @Nullable Object handler) throws IOException {
        String[] supportedMethods = ex.getSupportedMethods();
        if (supportedMethods != null) {
            response.setHeader("Allow", StringUtils.arrayToDelimitedString(supportedMethods, ", "));
        }
        log.error("访问[{}]类型[{}]不支持", request.getRequestURI(),request.getMethod().toUpperCase(Locale.ROOT));
        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ex.getMessage());
        return new ModelAndView();
    }
}
