package com.fs.erp.service.impl;

import com.fs.erp.constant.ErpTypeConstant;
import com.fs.erp.domain.ErpOrder;
import com.fs.erp.domain.ErpRefundOrder;
import com.fs.erp.domain.ErpUser;
import com.fs.erp.dto.*;
import com.fs.erp.service.IErpOrderService;
import com.fs.erp.utils.ErpContextHolder;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * ERP订单服务动态代理类
 * 通过ErpContextHolder获取当前ERP类型，实现多ERP系统无感切换
 */
@Slf4j
@Service
@Primary
public class ErpOrderServiceProxy implements IErpOrderService {
    private final RateLimiter rateLimiter = RateLimiter.create(5.0);

    /**
     * 存储所有实现的ERP订单服务
     */
    private final Map<String, IErpOrderService> erpOrderServiceMap = new HashMap<>();

    /**
     * 构造函数注入各种ERP实现
     */
    @Autowired
    public ErpOrderServiceProxy(
            @Qualifier("JSTErpOrderServiceImpl") IErpOrderService jstErpOrderService,
            @Qualifier("erpOrderServiceImpl") IErpOrderService gyErpOrderService) {
        erpOrderServiceMap.put(ErpTypeConstant.JST_ERP, jstErpOrderService);
        erpOrderServiceMap.put(ErpTypeConstant.GY_ERP, gyErpOrderService);
    }

    /**
     * 获取当前应该使用的ERP服务实现
     * @return 对应ERP类型的服务实现
     */
    private IErpOrderService getCurrentErpService() {
        String erpType = ErpContextHolder.getErpType();

        IErpOrderService service = erpOrderServiceMap.get(erpType);
        if (service == null) {
            throw new IllegalStateException("未找到ERP类型 [" + erpType + "] 的实现");
        }
        return service;
    }

    @Override
    public ErpOrderResponse addOrder(ErpOrder order) {
        return getCurrentErpService().addOrder(order);
    }

    @Override
    public ErpOrderResponse refundOrder(ErpRefundOrder order) {
        return getCurrentErpService().refundOrder(order);
    }

    @Override
    public ErpDeliverysResponse getDeliver(ErpDeliverysRequest param) {
        return getCurrentErpService().getDeliver(param);
    }

    @Override
    public ErpOrderQueryResponse getOrder(ErpOrderQueryRequert param) {
        if(StringUtils.equals(ErpContextHolder.getErpType(), ErpTypeConstant.JST_ERP)) {
            // 最大重试次数
            int maxRetries = 3;
            // 当前重试次数
            int retryCount = 0;

            while (retryCount < maxRetries) {
                if (rateLimiter.tryAcquire()) {
                    // 获取到令牌，直接执行请求
                    return getCurrentErpService().getOrder(param);
                }

                // 重试计数增加
                retryCount++;

                if (retryCount < maxRetries) {
                    try {
                        // 每次重试间隔时间递增：500ms, 1000ms, 1500ms...
                        long waitTime = 1000 * retryCount;
                        Thread.sleep(waitTime);
                        log.info("ERP请求被限流，等待{}ms后第{}次重试", waitTime, retryCount);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }

            // 达到最大重试次数后仍无法获取令牌，才抛出异常
            throw new RuntimeException("请求过于频繁，请稍后再试");
        }
        return getCurrentErpService().getOrder(param);
    }

    @Override
    public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
        return getCurrentErpService().refundUpdate(param);
    }
}
