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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ycwl.basic.puzzle.entity.PuzzleFillRuleEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 条件评估器集成测试
 */
@DisplayName("条件评估器集成测试")
class ConditionEvaluatorTest {

    private ConditionEvaluator evaluator;
    private ObjectMapper objectMapper;

    @BeforeEach
    void setUp() {
        objectMapper = new ObjectMapper();

        // 注册所有策略
        List<ConditionStrategy> strategies = Arrays.asList(
                new DeviceCountConditionStrategy(),
                new DeviceIdMatchConditionStrategy(),
                new AlwaysConditionStrategy()
        );

        evaluator = new ConditionEvaluator(strategies, objectMapper);
    }

    @Test
    @DisplayName("应该正确评估DEVICE_COUNT类型的规则")
    void shouldEvaluateDeviceCountRule() {
        // Given
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(1L);
        rule.setRuleName("4机位规则");
        rule.setConditionType("DEVICE_COUNT");
        rule.setConditionValue("{\"deviceCount\": 4}");

        ConditionContext context = ConditionContext.builder()
                .deviceCount(4)
                .build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then
        assertTrue(result);
    }

    @Test
    @DisplayName("DEVICE_COUNT_RANGE类型策略未实现，应该返回false")
    void shouldReturnFalseForUnimplementedDeviceCountRangeRule() {
        // Given - DEVICE_COUNT_RANGE 策略未实现
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(2L);
        rule.setRuleName("2-5机位规则");
        rule.setConditionType("DEVICE_COUNT_RANGE");  // 未实现的策略类型
        rule.setConditionValue("{\"minCount\": 2, \"maxCount\": 5}");

        ConditionContext context = ConditionContext.builder()
                .deviceCount(3)
                .build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then - 未实现的策略应该返回false
        assertFalse(result);
    }

    @Test
    @DisplayName("应该正确评估ALWAYS类型的规则")
    void shouldEvaluateAlwaysRule() {
        // Given
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(3L);
        rule.setRuleName("兜底规则");
        rule.setConditionType("ALWAYS");
        rule.setConditionValue("{}");

        ConditionContext context = ConditionContext.builder()
                .deviceCount(999)
                .build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then
        assertTrue(result);
    }

    @Test
    @DisplayName("应该正确评估DEVICE_ID_MATCH类型的规则-单机位匹配")
    void shouldEvaluateDeviceIdMatchRuleSingleDevice() {
        // Given
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(4L);
        rule.setRuleName("指定机位规则");
        rule.setConditionType("DEVICE_ID_MATCH");
        rule.setConditionValue("{\"deviceId\": 200}");

        ConditionContext context = ConditionContext.builder()
                .deviceIds(Arrays.asList(100L, 200L, 300L))
                .build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then
        assertTrue(result);
    }

    @Test
    @DisplayName("应该正确评估DEVICE_ID_MATCH类型的规则-多机位ANY匹配")
    void shouldEvaluateDeviceIdMatchRuleMultipleDevicesAny() {
        // Given
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(5L);
        rule.setRuleName("多机位ANY规则");
        rule.setConditionType("DEVICE_ID_MATCH");
        rule.setConditionValue("{\"deviceIds\": [200, 400], \"matchMode\": \"ANY\"}");

        ConditionContext context = ConditionContext.builder()
                .deviceIds(Arrays.asList(100L, 200L, 300L))
                .build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then
        assertTrue(result);
    }

    @Test
    @DisplayName("应该正确评估DEVICE_ID_MATCH类型的规则-多机位ALL匹配")
    void shouldEvaluateDeviceIdMatchRuleMultipleDevicesAll() {
        // Given
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(6L);
        rule.setRuleName("多机位ALL规则");
        rule.setConditionType("DEVICE_ID_MATCH");
        rule.setConditionValue("{\"deviceIds\": [100, 200], \"matchMode\": \"ALL\"}");

        ConditionContext context = ConditionContext.builder()
                .deviceIds(Arrays.asList(100L, 200L, 300L))
                .build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then
        assertTrue(result);
    }

    @Test
    @DisplayName("当条件类型不存在时应该返回false")
    void shouldReturnFalseWhenConditionTypeNotFound() {
        // Given
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(4L);
        rule.setRuleName("未知类型规则");
        rule.setConditionType("UNKNOWN_TYPE");
        rule.setConditionValue("{}");

        ConditionContext context = ConditionContext.builder().build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then
        assertFalse(result);
    }

    @Test
    @DisplayName("当conditionValue格式错误时应该返回false")
    void shouldReturnFalseWhenConditionValueIsInvalid() {
        // Given
        PuzzleFillRuleEntity rule = new PuzzleFillRuleEntity();
        rule.setId(5L);
        rule.setRuleName("格式错误规则");
        rule.setConditionType("DEVICE_COUNT");
        rule.setConditionValue("invalid json");

        ConditionContext context = ConditionContext.builder()
                .deviceCount(4)
                .build();

        // When
        boolean result = evaluator.evaluate(rule, context);

        // Then
        assertFalse(result);
    }

    @Test
    @DisplayName("应该支持多个策略并正确路由")
    void shouldSupportMultipleStrategies() {
        // Test DEVICE_COUNT
        ConditionContext context1 = ConditionContext.builder()
                .deviceCount(4)
                .build();

        PuzzleFillRuleEntity rule1 = new PuzzleFillRuleEntity();
        rule1.setConditionType("DEVICE_COUNT");
        rule1.setConditionValue("{\"deviceCount\": 4}");
        assertTrue(evaluator.evaluate(rule1, context1));

        // Test DEVICE_ID_MATCH
        ConditionContext context2 = ConditionContext.builder()
                .deviceIds(Arrays.asList(100L, 200L, 300L))
                .build();

        PuzzleFillRuleEntity rule3 = new PuzzleFillRuleEntity();
        rule3.setConditionType("DEVICE_ID_MATCH");
        rule3.setConditionValue("{\"deviceId\": 200}");
        assertTrue(evaluator.evaluate(rule3, context2));

        // Test ALWAYS
        PuzzleFillRuleEntity rule4 = new PuzzleFillRuleEntity();
        rule4.setConditionType("ALWAYS");
        rule4.setConditionValue("{}");
        assertTrue(evaluator.evaluate(rule4, context1));
    }
}
