package com.sino.mci.channel.wecom.support;

import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 企业微信 CP {@link WxCpService} 工厂。
 *
 * <p>根据企业 ID、应用 ID、应用 Secret 构建 {@link WxCpService}，并按账号维度缓存。
 * 若上下文中存在 {@link StringRedisTemplate}，则 token 使用 Redis 缓存。</p>
 */
@Component
public class WeComServiceFactory {

    private static final Logger log = LoggerFactory.getLogger(WeComServiceFactory.class);

    private final StringRedisTemplate redisTemplate;
    private final Map<String, WxCpService> serviceCache = new ConcurrentHashMap<>();

    public WeComServiceFactory(ObjectProvider<StringRedisTemplate> redisTemplateProvider) {
        this.redisTemplate = redisTemplateProvider.getIfAvailable();
    }

    /**
     * 根据 config 获取或创建 WxCpService。
     *
     * @param config 必须包含 corp_id、agent_id、secret
     * @return WxCpService 实例；配置缺失时返回 null
     */
    public WxCpService getOrCreateService(Map<String, Object> config) {
        if (config == null) {
            return null;
        }
        String corpId = getString(config, "corp_id");
        String agentId = getString(config, "agent_id");
        String secret = getString(config, "secret");
        if (corpId == null || agentId == null || secret == null) {
            log.warn("[WeCom] 缺少必要配置：corp_id/agent_id/secret");
            return null;
        }
        return getOrCreateService(corpId, Integer.valueOf(agentId), secret);
    }

    /**
     * 根据 corpId/agentId/secret 获取或创建 WxCpService。
     */
    public WxCpService getOrCreateService(String corpId, Integer agentId, String secret) {
        String key = corpId + ":" + agentId;
        return serviceCache.computeIfAbsent(key, k -> createService(corpId, agentId, secret));
    }

    private WxCpService createService(String corpId, Integer agentId, String secret) {
        WeComAccessTokenCache configStorage = new WeComAccessTokenCache(corpId, agentId, secret, redisTemplate);
        WxCpServiceImpl service = new WxCpServiceImpl();
        service.setWxCpConfigStorage(configStorage);
        log.info("[WeCom] 已创建 WxCpService：corpId={}, agentId={}", corpId, agentId);
        return service;
    }

    /**
     * 当前缓存中是否只存在一个账号。
     */
    public boolean hasSingleAccount() {
        return serviceCache.size() == 1;
    }

    /**
     * 获取缓存中唯一的账号服务；不存在或不唯一时返回 null。
     */
    public WxCpService getSingleAccountService() {
        if (serviceCache.size() != 1) {
            return null;
        }
        return serviceCache.values().iterator().next();
    }

    private String getString(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        return value.toString().trim();
    }
}
