package com.ycwl.basic.puzzle.fill.condition;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.puzzle.entity.PuzzleFillRuleEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 条件评估器
 * 使用策略模式,根据conditionType动态选择评估策略
 */
@Slf4j
@Component
public class ConditionEvaluator {

    private final Map<String, ConditionStrategy> strategyMap;
    private final ObjectMapper objectMapper;

    @Autowired
    public ConditionEvaluator(List<ConditionStrategy> strategies, ObjectMapper objectMapper) {
        this.strategyMap = strategies.stream()
                .collect(Collectors.toMap(
                        ConditionStrategy::getSupportedType,
                        Function.identity()
                ));
        this.objectMapper = objectMapper;
        log.info("初始化条件评估器,已注册{}个策略: {}", strategyMap.size(), strategyMap.keySet());
    }

    /**
     * 评估规则条件是否匹配
     *
     * @param rule 规则实体
     * @param context 评估上下文
     * @return true-匹配, false-不匹配
     */
    public boolean evaluate(PuzzleFillRuleEntity rule, ConditionContext context) {
        String conditionType = rule.getConditionType();
        ConditionStrategy strategy = strategyMap.get(conditionType);

        if (strategy == null) {
            log.warn("未找到条件类型[{}]对应的评估策略,规则ID:{}", conditionType, rule.getId());
            return false;
        }

        try {
            JsonNode conditionValue = objectMapper.readTree(rule.getConditionValue());
            boolean result = strategy.evaluate(conditionValue, context);
            log.debug("规则[{}]条件评估结果: {}, 条件类型: {}, 条件值: {}",
                    rule.getRuleName(), result, conditionType, rule.getConditionValue());
            return result;
        } catch (Exception e) {
            log.error("规则[{}]条件评估异常,规则ID:{}", rule.getRuleName(), rule.getId(), e);
            return false;
        }
    }
}
