package com.sw.mes.store.global;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.sw.mes.core.api.system.YbFeignClients;
import com.sw.mes.core.dto.DictionaryItemDto;
import com.sw.mes.core.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

import static com.sw.mes.store.global.StoreNamespace.GLOBAL_SWITCH;

/**
 * 线边仓全局开关
 *
 * @Author：wanjia
 * @Date：2024/2/20 14:28
 */
@Component
@Slf4j
public class StoreGlobalSwitch {
    private static YbFeignClients ybFeignClients;

    private static final Cache<String, SwitchConfig> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(10, TimeUnit.SECONDS) // 设置缓存条目在写入10s后被移除
            .maximumSize(10000) // 设置缓存的最大容量为10000
            .build();


    @Autowired
    public StoreGlobalSwitch(YbFeignClients ybFeignClients) {
        StoreGlobalSwitch.ybFeignClients = ybFeignClients;
    }

    /**
     * 根据namespace和key进行查询开关是否开启
     *
     * @param namespace    分组，用于不同类型的数据隔离，调用时可以用{@link StoreNamespace}中的初始值
     *                     圆棒如检验的卡控namespace为：YB_CHECK
     * @param key          每个不同的值
     * @param defaultValue 默认值，如果发现底层服务出现问题时，可以自动熔断到default上面
     * @return true or false,true:可以进入后面的操作,false：不可以进入
     */
    public static boolean enable(String namespace, String key, boolean defaultValue) {
        SwitchConfig config = switchConfig(namespace, key, defaultValue);
        return config.isEnable();
    }

    /**
     * 获取完整的config对象，用于获取内部的值
     *
     * @param namespace    分组，用于不同类型的数据隔离，调用时可以用{@link StoreNamespace}中的初始值
     *                     圆棒如检验的卡控namespace为：YB_CHECK
     * @param key          每个不同的值
     * @param defaultValue 默认值，如果发现底层服务出现问题时，可以自动熔断到default上面
     * @return {@link SwitchConfig}
     */
    public static SwitchConfig switchConfig(String namespace, String key, boolean defaultValue) {
        SwitchConfig config;
        try {
            //增加一层cache，防止同一段时间内调用，会多次请求数据库
            config = cache.get(composeCacheKey(GLOBAL_SWITCH, namespace, key), () -> {
                //todo 这里可以用个超时时间来提升下体验
                Result<DictionaryItemDto> result
                        = ybFeignClients.findByThemeValueAndNameAndValueAndEnable(GLOBAL_SWITCH, namespace, key, true);
                if (result == null || result.getCode() != 200 || result.getData() == null) {
                    return new SwitchConfig(defaultValue);
                }
                return convert(result.getData(), defaultValue);
            });
        } catch (Exception e) {
            log.error("error in global switch switchConfig:", e);
            return new SwitchConfig(defaultValue);
        }
        return config;
    }


    private static SwitchConfig convert(DictionaryItemDto dictionaryItem, boolean defaultValue) {
        if (null == dictionaryItem) {
            return new SwitchConfig(defaultValue);
        }
        SwitchConfig config = new SwitchConfig();
        config.setNamespace(dictionaryItem.getName());
        config.setKey(dictionaryItem.getValue());
        config.setEnable(parseExtendVal(dictionaryItem.getExtendValue(), defaultValue));
        config.setValue(dictionaryItem.getExtendValue1());
        config.setDescription(dictionaryItem.getExtendValue2());
        return config;
    }


    /**
     * 解析扩展字段1（enable字段）
     *
     * @param extValue
     * @param defaultValue
     * @return
     */
    private static boolean parseExtendVal(String extValue, boolean defaultValue) {
        if (StringUtils.isBlank(extValue)) {
            return defaultValue;
        }
        if ("1".equals(extValue) || "true".equalsIgnoreCase(extValue)) {
            return true;
        }
        if ("0".equals(extValue) || "false".equalsIgnoreCase(extValue)) {
            return false;
        }
        return defaultValue;
    }

    private static String composeCacheKey(String theme, String namespace, String key) {
        return theme + "_" + namespace + "_" + key;
    }
}
