package com.fs.feishu.util;

import com.fs.course.config.CourseConfig;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * SOP群发/自动执行场景，飞书直链文档分片分配器。
 * 控制单个分片承载客户数量，实现租户维度文档分片负载均衡，规避飞书文档访问限流。
 */
public class FeishuDirectDocShardAllocator {

    private static final int DEFAULT_MAX_CUSTOMERS_PER_SHARD_MASS_SEND = 30;
    private static final int DEFAULT_MAX_CUSTOMERS_PER_SHARD_AUTO = 50;

    private final int maxCustomersPerShard;
    private final boolean refreshCacheBeforeUse;
    private final Map<String, AtomicInteger> counters = new ConcurrentHashMap<>();
    private final Set<String> cacheRefreshedKeys = ConcurrentHashMap.newKeySet();

    private FeishuDirectDocShardAllocator(int maxCustomersPerShard, boolean refreshCacheBeforeUse) {
        this.maxCustomersPerShard = maxCustomersPerShard > 0 ? maxCustomersPerShard : DEFAULT_MAX_CUSTOMERS_PER_SHARD_MASS_SEND;
        this.refreshCacheBeforeUse = refreshCacheBeforeUse;
    }

    /**
     * 群发场景分片分配器：消息推送前需要刷新文档缓存
     */
    public static FeishuDirectDocShardAllocator forMassSend(CourseConfig config) {
        return new FeishuDirectDocShardAllocator(resolveMaxCustomersPerShardForMassSend(config), true);
    }

    /**
     * SOP自动执行场景分片分配器：平缓流量，无需前置刷新文档缓存
     */
    public static FeishuDirectDocShardAllocator forAutoSop(CourseConfig config) {
        return new FeishuDirectDocShardAllocator(resolveMaxCustomersPerShardForAuto(config), false);
    }

    public static int resolveMaxCustomersPerShardForMassSend(CourseConfig config) {
        if (config == null || config.getFeishuDirectDocMaxCustomersPerShard() == null
                || config.getFeishuDirectDocMaxCustomersPerShard() <= 0) {
            return DEFAULT_MAX_CUSTOMERS_PER_SHARD_MASS_SEND;
        }
        return config.getFeishuDirectDocMaxCustomersPerShard();
    }

    public static int resolveMaxCustomersPerShardForAuto(CourseConfig config) {
        if (config != null && config.getFeishuDirectDocMaxCustomersPerShardAuto() != null
                && config.getFeishuDirectDocMaxCustomersPerShardAuto() > 0) {
            return config.getFeishuDirectDocMaxCustomersPerShardAuto();
        }
        if (config != null && config.getFeishuDirectDocMaxCustomersPerShard() != null
                && config.getFeishuDirectDocMaxCustomersPerShard() > 0) {
            return config.getFeishuDirectDocMaxCustomersPerShard();
        }
        return DEFAULT_MAX_CUSTOMERS_PER_SHARD_AUTO;
    }

    /**
     * 群发场景下，每个「销售+课节+账号」维度在同一次群发请求内只清一次缓存。
     *
     * @return true 代表当前维度首次标记，需要执行缓存刷新逻辑
     */
    public boolean markDirectDocCacheForRefresh(Long companyUserId, Long videoId, Long courseId, Long feishuAccountId) {
        if (!refreshCacheBeforeUse) {
            return false;
        }
        return cacheRefreshedKeys.add(buildKey(companyUserId, videoId, courseId, feishuAccountId));
    }

    /**
     * 获取当前客户分配到的分片编号，分片从0开始
     */
    public int nextShard(Long companyUserId, Long videoId, Long courseId, Long feishuAccountId) {
        String key = buildKey(companyUserId, videoId, courseId, feishuAccountId);
        int customerIndex = counters.computeIfAbsent(key, ignored -> new AtomicInteger(0)).getAndIncrement();
        return customerIndex / maxCustomersPerShard;
    }

    private static String buildKey(Long companyUserId, Long videoId, Long courseId, Long feishuAccountId) {
        return companyUserId + ":" + videoId + ":" + courseId + ":" + (feishuAccountId != null ? feishuAccountId : 0);
    }
}
