package ink.wgink.gateway.exception.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import ink.wgink.gateway.enums.ErrorResultCodeEnum;
import ink.wgink.gateway.exception.SignException;
import ink.wgink.gateway.exception.SystemException;
import ink.wgink.gateway.pojo.result.ErrorResult;
import lombok.SneakyThrows;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: ExceptionHandler
 * @Description: 异常处理
 * @Author: wanggeng
 * @Date: 2021/4/23 3:15 下午
 * @Version: 1.0
 */
// 至少设置-2，靠前设置，不然不工作，数值越小，越靠前
@Order(-2)
@Component
public class ExceptionHandler implements WebExceptionHandler {

    @SneakyThrows
    @Override
    public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
        // 设置响应头
        ServerHttpResponse response = serverWebExchange.getResponse();
        response.setStatusCode(HttpStatus.BAD_REQUEST);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);

        ErrorResult errorResult = new ErrorResult();
        errorResult.setCode(getErrorCode(throwable));
        errorResult.setMsg(getErrorMessage(throwable));

        DataBuffer dataBuffer = response.bufferFactory().wrap(new ObjectMapper().writeValueAsBytes(errorResult));
        return response.writeWith(Mono.just(dataBuffer));
    }

    /**
     * 获取异常内容
     *
     * @param throwable
     * @return
     */
    public String getErrorMessage(Throwable throwable) {
        if (throwable instanceof SystemException) {
            return throwable.getMessage();
        } else {
            throwable.printStackTrace();
            return throwable.toString();
        }
    }

    /**
     * 获取错误编码
     *
     * @param throwable
     * @return
     */
    public Integer getErrorCode(Throwable throwable) {
        if (throwable instanceof SignException) {
            return ErrorResultCodeEnum.USERNAME_PASSWORD_ERROR.getValue();
        }
        return ErrorResultCodeEnum.SYSTEM_ERROR.getValue();
    }

}
