package com.tzy.common.dto.pay;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 支付通道分配
 */
@Slf4j
public class AllocatePayChannels {
    private static Map<String, List<PaymentChannel>> globalChannelDataByType=new HashMap<>();
    private static Map<String,Integer> totalWeightByType=new HashMap<>();

    private static synchronized void initGlobalChannels(List<PaymentChannel> globalChannels, String channelType) {
        try {
            List<PaymentChannel> globalChannelsByType = globalChannelDataByType.get(channelType);
            if (globalChannelsByType == null) {
                globalChannelDataByType.put(channelType, globalChannels);
                int totalWeight = globalChannels.stream().mapToInt(PaymentChannel::getWeight).sum();
                totalWeightByType.put(channelType, totalWeight);
                return;
            }

            if (globalChannelsByType.size() != globalChannels.size()) {
                Map<String, Integer> channelWeightMap = globalChannelsByType.stream().collect(Collectors.toMap(PaymentChannel::getPaymentSubType, PaymentChannel::getCurrentWeight));
                int totalWeight = globalChannels.stream().mapToInt(PaymentChannel::getWeight).sum();
                totalWeightByType.put(channelType, totalWeight);
                globalChannels.stream()
                        .filter(c -> channelWeightMap.containsKey(c.getPaymentSubType()))
                        .forEach(c -> c.setCurrentWeight(new AtomicInteger(channelWeightMap.get(c.getPaymentSubType()))));
                globalChannelDataByType.put(channelType, globalChannels);
            }
        } catch (Exception e) {
            log.error("支付通道初始化异常:", e);
        }
    }

    public static String allocatePaymentChannel(List<PaymentChannel> userChannels, List<PaymentChannel> globalChannels, String channelType) {
        if (CollectionUtils.isEmpty(userChannels) || CollectionUtils.isEmpty(globalChannels)) {
            return null;
        }
        initGlobalChannels(globalChannels, channelType);
        List<String> userSelectedChannel = userChannels.stream().map(PaymentChannel::getPaymentSubType).collect(Collectors.toList());
        List<PaymentChannel> paymentChannels = globalChannelDataByType.get(channelType);
        List<PaymentChannel> selectedChannels = paymentChannels.stream().filter(channel -> userSelectedChannel.contains(channel.getPaymentSubType())).collect(Collectors.toList());
        PaymentChannel selectedChannel = selectedChannels.stream().max(Comparator.comparingInt(PaymentChannel::getCurrentWeight)).orElse(null);
        if (selectedChannel != null) {
            selectedChannel.subtractCurrentWeight(totalWeightByType.get(channelType));
            paymentChannels.forEach(channel -> channel.addCurrentWeight(channel.getWeight()));
            //log.debug("分配支付通道:{}", selectedChannel.getPaymentSubType());
            //paymentChannels.forEach(c -> log.debug("分配支付通道权重变化:{}", c));
        }
        return selectedChannel != null ? selectedChannel.getPaymentSubType() : null;
    }
}
