package com.sdtool.webcore.servlet;

import com.sdtool.common.api.ConfigService;
import com.sdtool.common.api.ERPService;
import com.sdtool.common.api.mall.MallApiCallService;
import com.sdtool.common.datas.HttpCode;
import com.sdtool.common.entity.base.DataBaseMultiItemEx;
import com.sdtool.common.entity.base.InvokeCallParams;
import com.sdtool.common.entity.base.InvokeCallResult;
import com.sdtool.common.entity.system.ConfigValue;
import com.sdtool.common.tool.ERPUtils;
import com.sweetfish.convert.json.JsonConvert;
import com.sweetfish.net.WorkThread;
import com.sweetfish.net.http.*;
import com.sweetfish.service.RetResult;
import com.sweetfish.util.AnyValue;
import com.sweetfish.util.AutoLoad;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Resource;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;

/**
 * @Author: xl Created on 2024-06-11
 * @Content:
 */
@AutoLoad(false)
@WebServlet(name = "商城应用API中心", value = {"/mallCall/*"}, comment = "商城应用API中心")
public class MallCallServlet extends HttpServlet {

    @Resource
    JsonConvert jsonConvert;

    @Resource
    MallApiCallService mallApiCallService;

    @Resource
    ERPService erpService;

    @Resource
    ConfigService configService;

    private ExecutorService getExecutor() {
        Thread thread = Thread.currentThread();
        if (thread instanceof WorkThread) {
            return ((WorkThread) thread).getExecutor();
        }
        return ForkJoinPool.commonPool();
    }

    private final Logger logger = LogManager.getLogger(this.getClass().getSimpleName());

    @Override
    public void init(HttpContext context, AnyValue config) {
        super.init(context, config);
    }

    @Override
    public void destroy(HttpContext context, AnyValue config) {
        super.destroy(context, config);
    }

    /**
     * 基础执行函数
     * 注意：其它业务错误码从10000开始，不要使用10000以下的数字，避免错误码不统一
     *
     * @param request  http请求
     * @param response http response
     */
    private void call(HttpRequest request, HttpResponse response) {
        CompletableFuture.supplyAsync(() -> {
            String json = request.getBodyUTF8();

            if (StringUtils.isEmpty(json)) {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "POST数据为空");
            }

            InvokeCallParams invokeParams;
            try {
                invokeParams = jsonConvert.convertFrom(InvokeCallParams.class, json);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                //防止乱post数据
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "JSON格式不正确");
            }

            if (invokeParams == null) {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "JSON格式不正确");
            }

            if (StringUtils.isEmpty(invokeParams.getBusinessMethod())) {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "参数中缺少businessMethod");
            }

            if (StringUtils.isEmpty(invokeParams.getClientCode())) {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "参数中缺少clientCode");
            }

            DataBaseMultiItemEx itemData = erpService.getERPSupplierInfoByCode(invokeParams.getClientCode());
            if (itemData == null) {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "未获取到商户信息{" + invokeParams.getClientCode() + "}");
            }

            String dataSourceId = itemData.getDataBaseAlias();
            long supplierCode = Long.parseLong(itemData.getShardingKey());

            if ((StringUtils.isBlank(dataSourceId)) || (supplierCode <= 0L)) {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "开发商配置错误");
            }

            ConfigValue mallCallConfig = configService.getRedisConfigValue("mallCallKey",dataSourceId,supplierCode);
            if ((mallCallConfig == null) || StringUtils.isBlank(mallCallConfig.getConfigValue1())) {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "商城后台未配置访问key");
            }

            if (invokeParams.verifySign(mallCallConfig.getConfigValue1())) {
                invokeParams.setDataSourceId(dataSourceId);
                invokeParams.setSupplierCode(supplierCode);
                RetResult<InvokeCallResult> callResult = mallApiCallService.callAPi(invokeParams, ERPUtils.getSysRemoteErpUser(), dataSourceId, supplierCode);
                if (callResult.isSuccess()) {
                    return callResult.getResult();
                } else {
                    return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), callResult.getRetinfo());
                }
            } else {
                return InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "签名错误");
            }
        }, getExecutor()).whenComplete((v, e) -> {
            if (e != null) {
                logger.error(e.getMessage(), e);
                response.finish(InvokeCallResult.error(HttpCode.INTERNAL_SERVER_ERROR.value(), "网络通信错误，请稍后重试"));
                return;
            }
            response.finish(v);
        });
    }

    @HttpMapping(url = "/mallCall/gateway", methods = {"POST"}, comment = "网关入口")
    public void gateway(HttpRequest request, HttpResponse response) {
        call(request, response);
    }

}
