package cn.axzo.workflow.core.common.utils;

import java.util.function.Consumer;
import java.util.function.Supplier;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.framework.domain.web.BizException;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import static cn.axzo.framework.domain.web.code.BaseCode.BAD_REQUEST;

/**
 * 内部api 使用 服务与 yoke 下游服务 下游服务统一使用 ApiResult
 * @author tanjie@axzo.cn
 * @date 2022/5/23 11:08
 */
@Slf4j
public class RpcInternalUtil {

    /**
     * 常用的RPC请求返回值解析，如果 被请求方 返回非200会抛出异常
     */
    public static <T> ApiResult<T> rpcProcessor(Supplier<ApiResult<T>> supplier, String operationType, Object... param) {

        return rpcProcessorMayThrow(supplier, operationType, (msg) -> {
            throw new ServiceException(msg);
        }, param);
    }

    public static <T> ApiResult<T> rpcProcessorMayThrow(Supplier<ApiResult<T>> supplier, String operationType, Consumer<String> throwConsumer, Object... param) {
        AssertUtil.notNull(throwConsumer, "自定义的异常处理不可为空");
        log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
        ApiResult<T> result = null;

        try {
            result = supplier.get();
        } catch (Throwable e) {
            log.warn("rpc process error:{}", e.getMessage());
            throwConsumer.accept("服务调用异常");
        }

        log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result));
        Assert.notNull(result, "服务调用异常");
        // 200自定义处理
        if (HttpStatus.HTTP_OK != result.getCode()) {
            throwConsumer.accept(result.getMsg());
        }
        return result;
    }

    /**
     * 常用的RPC请求返回值解析，如果 被请求方 返回非200会抛出异常
     */
    public static <T> ApiPageResult<T> rpcPageProcessor(Supplier<ApiPageResult<T>> supplier, String operationType, Object... param) {

        return rpcPageProcessorMayThrow(supplier, operationType, (msg) -> {
            throw new ServiceException(msg);
        }, param);
    }

    public static <T> ApiPageResult<T> rpcPageProcessorMayThrow(Supplier<ApiPageResult<T>> supplier, String operationType, Consumer<String> throwConsumer, Object... param) {
        AssertUtil.notNull(throwConsumer, "自定义的异常处理不可为空");
        log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
        ApiPageResult<T> result = null;
        try {
            result = supplier.get();
        } catch (Throwable t) {
            log.warn("rpc process error:{}", t.getMessage());
            throwConsumer.accept("服务调用异常");
        }
        log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result));
        Assert.notNull(result, "服务调用异常");
        // 200自定义处理
        if (HttpStatus.HTTP_OK != result.getCode()) {
            throwConsumer.accept(result.getMsg());
        }
        return result;
    }

    public static  <T> T checkAndGetData(ApiResult<T> result) {
        if (result.isError()) {
            throw new BizException(result.getRespCode(), result.getMsg());
        }
        T data = result.getData();
        if (data == null) {
            throw new BizException(BAD_REQUEST, "数据不存在");
        }
        return data;
    }

    public static <T> CommonResponse<T> commonRpcProcessor(Supplier<CommonResponse<T>> supplier, String operationType, Object... param) {

        return commonRpcProcessorMayThrow(supplier, operationType, (msg) -> {
            throw new ServiceException(msg);
        }, param);
    }

    public static <T> CommonResponse<T> commonRpcProcessorMayThrow(Supplier<CommonResponse<T>> supplier, String operationType,
                                                              Consumer<String> throwConsumer, Object... param) {
        AssertUtil.notNull(throwConsumer, "自定义的异常处理不可为空");
        log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
        CommonResponse<T> result = null;

        try {
            result = supplier.get();
        } catch (Throwable e) {
            log.warn("rpc process error:{}", e.getMessage());
            throwConsumer.accept("服务调用异常");
        }

        log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result));
        Assert.notNull(result, "服务调用异常");
        // 200自定义处理
        if (HttpStatus.HTTP_OK != result.getCode()) {
            throwConsumer.accept(result.getMsg());
        }
        return result;
    }


}
