package com.yhy.module.core.service.quota;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import com.yhy.module.core.dal.dataobject.quota.QuotaRateItemDO;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
 * 定额费率项计算逻辑测试
 * 
 * 测试默认阶梯规则的计算逻辑
 */
@DisplayName("定额费率项计算逻辑测试")
public class QuotaRateItemCalculationTest {

    @Test
    @DisplayName("测试阶梯规则 - 基数50万以内")
    public void testTierRule_Under50() {
        // 模拟费率项配置
        QuotaRateItemDO rateItem = createRateItemWithTiers();
        
        // 基数值：30万
        BigDecimal baseValue = new BigDecimal("30");
        
        // 预期结果：字段1=0.224
        Map<Integer, BigDecimal> expected = new HashMap<>();
        expected.put(1, new BigDecimal("0.224"));
        
        // 验证匹配第一个阶梯
        Map<String, Object> valueRules = rateItem.getValueRules();
        List<Map<String, Object>> tiers = (List<Map<String, Object>>) valueRules.get("tiers");
        
        Map<String, Object> matchedTier = findMatchedTier(tiers, baseValue);
        assertNotNull(matchedTier);
        assertEquals(new BigDecimal("50"), new BigDecimal(matchedTier.get("threshold").toString()));
    }

    @Test
    @DisplayName("测试阶梯规则 - 基数50-100万之间")
    public void testTierRule_Between50And100() {
        QuotaRateItemDO rateItem = createRateItemWithTiers();
        
        // 基数值：80万
        BigDecimal baseValue = new BigDecimal("80");
        
        // 预期结果：字段1=0.301
        Map<String, Object> valueRules = rateItem.getValueRules();
        List<Map<String, Object>> tiers = (List<Map<String, Object>>) valueRules.get("tiers");
        
        Map<String, Object> matchedTier = findMatchedTier(tiers, baseValue);
        assertNotNull(matchedTier);
        assertEquals(new BigDecimal("100"), new BigDecimal(matchedTier.get("threshold").toString()));
    }

    @Test
    @DisplayName("测试阶梯规则 - 基数超过最大阈值")
    public void testTierRule_ExceedMax() {
        QuotaRateItemDO rateItem = createRateItemWithTiers();
        
        // 基数值：5000万
        BigDecimal baseValue = new BigDecimal("5000");
        
        // 预期结果：使用最后一个阶梯
        Map<String, Object> valueRules = rateItem.getValueRules();
        List<Map<String, Object>> tiers = (List<Map<String, Object>>) valueRules.get("tiers");
        
        Map<String, Object> matchedTier = findMatchedTier(tiers, baseValue);
        // 如果没有匹配，应该使用最后一个阶梯
        if (matchedTier == null) {
            matchedTier = tiers.get(tiers.size() - 1);
        }
        assertNotNull(matchedTier);
    }

    @Test
    @DisplayName("测试阶梯规则 + 增量规则")
    public void testTierWithIncrement() {
        QuotaRateItemDO rateItem = createRateItemWithTiersAndIncrements();
        
        // 基数值：1200万（超过1000万基础阈值200万）
        BigDecimal baseValue = new BigDecimal("1200");
        
        // 预期结果：
        // 1. 阶梯基础值：字段1=0.301（匹配最后一个阶梯）
        // 2. 增量计算：(1200-1000)/100 * 0.036 = 2 * 0.036 = 0.072
        // 3. 最终结果：0.301 + 0.072 = 0.373
        
        Map<String, Object> valueRules = rateItem.getValueRules();
        List<Map<String, Object>> tiers = (List<Map<String, Object>>) valueRules.get("tiers");
        List<Map<String, Object>> increments = (List<Map<String, Object>>) valueRules.get("increments");
        
        assertNotNull(tiers);
        assertNotNull(increments);
        assertFalse(increments.isEmpty());
    }

    // ==================== 辅助方法 ====================

    /**
     * 创建只有阶梯规则的费率项
     */
    private QuotaRateItemDO createRateItemWithTiers() {
        QuotaRateItemDO rateItem = new QuotaRateItemDO();
        rateItem.setValueMode("dynamic");
        
        Map<String, Object> settings = new HashMap<>();
        Map<String, Object> valueRules = new HashMap<>();
        
        // 阶梯规则
        List<Map<String, Object>> tiers = new ArrayList<>();
        
        // 第1档：≤50万，费率0.224%
        Map<String, Object> tier1 = new HashMap<>();
        tier1.put("seq", 1);
        tier1.put("threshold", new BigDecimal("50"));
        tier1.put("compareType", "lte");
        Map<String, Object> fieldValues1 = new HashMap<>();
        fieldValues1.put("1", new BigDecimal("0.224"));
        tier1.put("fieldValues", fieldValues1);
        tiers.add(tier1);
        
        // 第2档：≤100万，费率0.301%
        Map<String, Object> tier2 = new HashMap<>();
        tier2.put("seq", 2);
        tier2.put("threshold", new BigDecimal("100"));
        tier2.put("compareType", "lte");
        Map<String, Object> fieldValues2 = new HashMap<>();
        fieldValues2.put("1", new BigDecimal("0.301"));
        tier2.put("fieldValues", fieldValues2);
        tiers.add(tier2);
        
        valueRules.put("tiers", tiers);
        settings.put("valueRules", valueRules);
        rateItem.setSettings(settings);
        
        return rateItem;
    }

    /**
     * 创建包含阶梯规则和增量规则的费率项
     */
    private QuotaRateItemDO createRateItemWithTiersAndIncrements() {
        QuotaRateItemDO rateItem = createRateItemWithTiers();
        
        Map<String, Object> settings = rateItem.getSettings();
        Map<String, Object> valueRules = (Map<String, Object>) settings.get("valueRules");
        
        // 增量规则
        List<Map<String, Object>> increments = new ArrayList<>();
        
        Map<String, Object> increment1 = new HashMap<>();
        increment1.put("seq", 1);
        increment1.put("step", new BigDecimal("100"));
        increment1.put("baseThreshold", new BigDecimal("1000"));
        Map<String, Object> fieldIncrements = new HashMap<>();
        fieldIncrements.put("1", new BigDecimal("0.036"));
        increment1.put("fieldIncrements", fieldIncrements);
        increments.add(increment1);
        
        valueRules.put("increments", increments);
        
        return rateItem;
    }

    /**
     * 查找匹配的阶梯
     */
    private Map<String, Object> findMatchedTier(List<Map<String, Object>> tiers, BigDecimal baseValue) {
        // 按阈值排序
        tiers.sort(Comparator.comparing(t -> new BigDecimal(t.get("threshold").toString())));
        
        for (Map<String, Object> tier : tiers) {
            BigDecimal threshold = new BigDecimal(tier.get("threshold").toString());
            String compareType = (String) tier.getOrDefault("compareType", "lte");
            
            boolean matched = false;
            switch (compareType) {
                case "lte":
                    matched = baseValue.compareTo(threshold) <= 0;
                    break;
                case "lt":
                    matched = baseValue.compareTo(threshold) < 0;
                    break;
                case "gte":
                    matched = baseValue.compareTo(threshold) >= 0;
                    break;
                case "gt":
                    matched = baseValue.compareTo(threshold) > 0;
                    break;
            }
            
            if (matched) {
                return tier;
            }
        }
        
        return null;
    }
}
