package com.czg.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.io.resource.NoResourceException;
import com.czg.resp.CzgRespCode;
import com.czg.resp.CzgResult;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;

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

/**
 * @author GYJoker
 */
@RestControllerAdvice
@Slf4j
public class CzgControllerAdvice {
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> errorHandler(Exception ex) {
        setErrorLog(ex);
        return CzgResult.failure(CzgRespCode.SYSTEM_ERROR.getCode(), ex.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = NoResourceFoundException.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> errorHandler(NoResourceFoundException ex) {
        log.error("资源不存在");
        return CzgResult.failure(CzgRespCode.SYSTEM_ERROR.getCode(), ex.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = NotLoginException.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> notLoginErrorHandler(NotLoginException ex) {
        return CzgResult.failure(CzgRespCode.NOT_LOGIN.getCode(), CzgRespCode.NOT_LOGIN + ":" + ex.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = ApiNotPrintException.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> apiNotPrintErrorHandler(ApiNotPrintException ex) {
        setErrorLog(ex);
        return CzgResult.failure(ex.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> invalidFormatExceptionErrorHandler(HttpMessageNotReadableException ex) {
        setErrorLog(ex);
        return CzgResult.failure(ex.getRootCause() == null ? ex.getMessage() : ex.getRootCause().getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = NotPermissionException.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> notPermissionErrorHandler(NotPermissionException ex) {
        return CzgResult.failure(CzgRespCode.UN_PERMISSION);
    }

    @ResponseBody
    @ExceptionHandler(value = NotRoleException.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> notRoleErrorHandler(NotRoleException ex) {
        return CzgResult.failure(CzgRespCode.UN_ROLE);
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public CzgResult<Object> requestParamException(MethodArgumentNotValidException ex) {
        setErrorLog(ex);
        List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
        String message = allErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";"));
        return CzgResult.failure(CzgRespCode.PARAM_ERROR.getCode(), message);
    }

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(CzgException.class)
    public CzgResult<Object> handleCzgException(CzgException ex) {
        setErrorLog(ex);
        return CzgResult.failure(ex.getCode(), ex.getMsg());
    }

    /**
     * 支付成功
     * 支付金额为零的统一处理
     */
    @ExceptionHandler(PaySuccessException.class)
    public CzgResult<Object> handlePaySuccessException() {
        return CzgResult.success();
    }

    /**
     * 订单超时 取消
     */
    @ExceptionHandler(OrderCancelException.class)
    public CzgResult<Object> handleOrderCancelException() {
        return CzgResult.failure(701,"订单已过期,请重新下单");
    }

    /**
     * 处理Hutool的断言抛出异常
     */
//    @ExceptionHandler(IllegalArgumentException.class)
//    public CzgResult<Object> handleAssertException(IllegalArgumentException ex) {
//        return CzgResult.failure(CzgRespCode.PARAM_ERROR.getCode(), ex.getMessage());
//    }

    /**
     * 处理Hutool的校验工具类抛出异常
     */
    @ExceptionHandler(ValidateException.class)
    public CzgResult<Object> handleValidateException(ValidateException ex) {
        log.error(ex.getMessage());
        return CzgResult.failure(CzgRespCode.PARAM_ERROR.getCode(), ex.getMessage());
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public CzgResult<Object> handleDuplicateKeyException(DuplicateKeyException ex) {
        setErrorLog(ex);
        return CzgResult.failure(CzgRespCode.RECORD_EXISTED);
    }

    private void setErrorLog(Exception ex) {
        log.error("错误",ex);
        log.error(ex.getMessage());
    }
}
