package com.usky.rule.cache;

import com.usky.common.redis.core.RedisHelper;
import com.usky.rule.util.JsonUtil;
import com.usky.rule.vo.ConditionExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 设备触发“包含分钟”条件缓存，使用 RedisHelper 存储。
 * 单条条件过期时间 1 天；按 ruleEngineId 可批量删除。
 */
@Component
public class DeviceTriggerIncludeMinuteCache {

    private static final String KEY_PREFIX = "ruleEngine:condition:";
    private static final String INDEX_KEY_PREFIX = "ruleEngine:keys:";
    private static final long EXPIRE_DAYS = 1L;

    @Autowired
    private RedisHelper redisHelper;

    public ConditionExpression getConditions(Long ruleEngineId, String device, String identifier, String expression) {
        String key = buildConditionKey(ruleEngineId, device, identifier, expression);
        if (!redisHelper.hasKey(key)) {
            return null;
        }
        Object val = redisHelper.get(key);
        if (val == null) {
            return null;
        }
        return JsonUtil.toObject(val.toString(), ConditionExpression.class);
    }

    public void setCondition(Long ruleEngineId, String device, String identifier, ConditionExpression condition) {
        String key = buildConditionKey(ruleEngineId, device, identifier, condition.getExpression());
        redisHelper.set(key, JsonUtil.toJson(condition), EXPIRE_DAYS, TimeUnit.DAYS);
        addToIndex(ruleEngineId, key);
    }

    public void removeCondition(Long ruleEngineId, String device, String identifier, String expression) {
        String key = buildConditionKey(ruleEngineId, device, identifier, expression);
        redisHelper.delete(key);
        removeFromIndex(ruleEngineId, key);
    }

    public void removeConditions(Long ruleEngineId, String device, String identifier, List<String> expressionList) {
        if (expressionList == null || expressionList.isEmpty()) {
            return;
        }
        for (String expression : expressionList) {
            removeCondition(ruleEngineId, device, identifier, expression);
        }
    }

    public void deleteConditions(Long ruleEngineId) {
        String indexKey = INDEX_KEY_PREFIX + ruleEngineId;
        if (!redisHelper.hasKey(indexKey)) {
            return;
        }
        Object val = redisHelper.get(indexKey);
        if (val != null) {
            List<String> keys = JsonUtil.parseJsonArray(val.toString(), String.class);
            if (keys != null) {
                for (String key : keys) {
                    redisHelper.delete(key);
                }
            }
        }
        redisHelper.delete(indexKey);
    }

    private static String buildConditionKey(Long ruleEngineId, String device, String identifier, String expression) {
        return KEY_PREFIX + ruleEngineId + ":" + device + ":" + identifier + ":" + expression;
    }

    private void addToIndex(Long ruleEngineId, String conditionKey) {
        String indexKey = INDEX_KEY_PREFIX + ruleEngineId;
        List<String> keys = getIndexKeys(indexKey);
        if (!keys.contains(conditionKey)) {
            keys.add(conditionKey);
            redisHelper.set(indexKey, JsonUtil.toJson(keys));
        }
    }

    private void removeFromIndex(Long ruleEngineId, String conditionKey) {
        String indexKey = INDEX_KEY_PREFIX + ruleEngineId;
        List<String> keys = getIndexKeys(indexKey);
        if (keys.remove(conditionKey)) {
            if (keys.isEmpty()) {
                redisHelper.delete(indexKey);
            } else {
                redisHelper.set(indexKey, JsonUtil.toJson(keys));
            }
        }
    }

    private List<String> getIndexKeys(String indexKey) {
        if (!redisHelper.hasKey(indexKey)) {
            return new ArrayList<>();
        }
        Object val = redisHelper.get(indexKey);
        if (val == null) {
            return new ArrayList<>();
        }
        List<String> list = JsonUtil.parseJsonArray(val.toString(), String.class);
        return list != null ? list : new ArrayList<>();
    }
}
