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

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.yhy.module.core.controller.admin.unit.vo.UnitRateSettingRespVO;
import com.yhy.module.core.controller.admin.unit.vo.UnitRateSettingSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateItemDO;
import com.yhy.module.core.dal.dataobject.workbench.WbRateItemDO;
import com.yhy.module.core.dal.dataobject.workbench.WbUnitRateSettingDO;
import com.yhy.module.core.dal.mysql.quota.QuotaRateItemMapper;
import com.yhy.module.core.dal.mysql.workbench.WbRateItemMapper;
import com.yhy.module.core.dal.mysql.workbench.WbUnitRateSettingMapper;
import com.yhy.module.core.service.quota.QuotaRateItemService;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 工程费率设定 Service 实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UnitRateSettingServiceImpl implements UnitRateSettingService {

    private final WbUnitRateSettingMapper unitRateSettingMapper;
    private final QuotaRateItemMapper quotaRateItemMapper;
    private final WbRateItemMapper wbRateItemMapper;
    private final QuotaRateItemService quotaRateItemService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UnitRateSettingRespVO saveOrUpdate(UnitRateSettingSaveReqVO saveReqVO) {
        // 查询是否已存在
        WbUnitRateSettingDO existingSetting = unitRateSettingMapper.selectByUnitIdAndRateItemId(
                saveReqVO.getUnitId(), saveReqVO.getRateItemId());
        
        WbUnitRateSettingDO settingDO;
        if (existingSetting != null) {
            // 更新
            settingDO = existingSetting;
            settingDO.setSelectedValueId(saveReqVO.getSelectedValueId());
            settingDO.setInputValue(saveReqVO.getInputValue());
            settingDO.setSettingName(saveReqVO.getSettingName());
        } else {
            // 新建
            settingDO = BeanUtils.toBean(saveReqVO, WbUnitRateSettingDO.class);
        }
        
        // 计算或使用用户提供的字段值
        Map<Integer, BigDecimal> fieldValues;
        if (saveReqVO.getFieldValues() != null && !saveReqVO.getFieldValues().isEmpty()) {
            // 用户直接提供了字段值（虚拟字段修改）
            fieldValues = existingSetting != null && existingSetting.getFieldValues() != null 
                    ? new HashMap<>(existingSetting.getFieldValues()) 
                    : new HashMap<>();
            // 合并用户修改的字段值
            // 注意：null 值也要保存，表示用户清空了该字段（显示为空）
            for (Map.Entry<Integer, BigDecimal> entry : saveReqVO.getFieldValues().entrySet()) {
                fieldValues.put(entry.getKey(), entry.getValue());
            }
        } else {
            // 通过选择或输入值计算字段值
            fieldValues = calculateFieldValues(saveReqVO);
        }
        settingDO.setFieldValues(fieldValues);
        
        // 保存
        if (existingSetting != null) {
            unitRateSettingMapper.updateById(settingDO);
        } else {
            // 首次保存时，设置基线值
            settingDO.setBaseValue(saveReqVO.getInputValue());
            settingDO.setBaseFieldValues(fieldValues);
            unitRateSettingMapper.insert(settingDO);
        }
        
        return BeanUtils.toBean(settingDO, UnitRateSettingRespVO.class);
    }

    @Override
    public List<UnitRateSettingRespVO> getListByUnitId(Long unitId) {
        List<WbUnitRateSettingDO> list = unitRateSettingMapper.selectByUnitId(unitId);
        return list.stream()
                .map(item -> BeanUtils.toBean(item, UnitRateSettingRespVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public UnitRateSettingRespVO getByUnitIdAndRateItemId(Long unitId, Long rateItemId) {
        WbUnitRateSettingDO setting = unitRateSettingMapper.selectByUnitIdAndRateItemId(unitId, rateItemId);
        return setting != null ? BeanUtils.toBean(setting, UnitRateSettingRespVO.class) : null;
    }

    @Override
    public void delete(Long id) {
        unitRateSettingMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initializeSettings(Long unitId, Long catalogItemId) {
        // 获取费率项树
        List<QuotaRateItemDO> rateItems = quotaRateItemMapper.selectListByCatalogItemId(catalogItemId);
        
        // 为每个目录节点创建初始设定
        for (QuotaRateItemDO rateItem : rateItems) {
            if ("directory".equals(rateItem.getNodeType())) {
                WbUnitRateSettingDO setting = new WbUnitRateSettingDO();
                setting.setUnitId(unitId);
                setting.setRateItemId(rateItem.getId());
                setting.setSettingName(rateItem.getName());
                
                // 设置默认值和基线值
                if (rateItem.getDefaultValue() != null) {
                    setting.setInputValue(rateItem.getDefaultValue());
                    setting.setBaseValue(rateItem.getDefaultValue());
                }
                
                unitRateSettingMapper.insert(setting);
            }
        }
    }

    /**
     * 计算字段值
     */
    private Map<Integer, BigDecimal> calculateFieldValues(UnitRateSettingSaveReqVO saveReqVO) {
        Map<Integer, BigDecimal> fieldValues = new HashMap<>();
        
        if (saveReqVO.getSelectedValueId() != null) {
            // 下拉模式：从选中的值节点获取字段值
            // 优先从快照表查询，如果不存在则从后台标准库查询
            Map<String, Object> settings = getSettingsFromRateItem(saveReqVO.getSelectedValueId());
            if (settings != null) {
                Object fieldValuesObj = settings.get("fieldValues");
                if (fieldValuesObj instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> fv = (Map<String, Object>) fieldValuesObj;
                    for (Map.Entry<String, Object> entry : fv.entrySet()) {
                        try {
                            int fieldIndex = Integer.parseInt(entry.getKey());
                            BigDecimal value = new BigDecimal(entry.getValue().toString());
                            fieldValues.put(fieldIndex, value);
                        } catch (NumberFormatException e) {
                            log.warn("无法解析字段值: key={}, value={}", entry.getKey(), entry.getValue());
                        }
                    }
                }
            }
        } else if (saveReqVO.getInputValue() != null) {
            // 填写模式：从快照表获取费率项的settings进行计算
            Map<String, Object> settings = getSettingsFromRateItem(saveReqVO.getRateItemId());
            if (settings != null && settings.containsKey("valueRules")) {
                // 使用快照数据的valueRules进行计算
                Map<Integer, BigDecimal> calculated = calculateDynamicFieldsFromSettings(
                        settings, saveReqVO.getInputValue());
                if (calculated != null) {
                    fieldValues.putAll(calculated);
                }
            }
            // 不再回退到后台标准库，只使用快照数据
        }
        
        return fieldValues;
    }

    /**
     * 从费率项获取settings（只查询快照表）
     */
    private Map<String, Object> getSettingsFromRateItem(Long rateItemId) {
        // 只从快照表查询，不回退到后台标准库
        WbRateItemDO wbRateItem = wbRateItemMapper.selectById(rateItemId);
        if (wbRateItem != null) {
            log.debug("[费率设置] 从快照表读取费率项, rateItemId={}", rateItemId);
            return wbRateItem.getSettings();
        }
        
        log.warn("[费率设置] 快照表中费率项不存在, rateItemId={}", rateItemId);
        return null;
    }

    /**
     * 根据settings中的valueRules计算动态字段值
     */
    @SuppressWarnings("unchecked")
    private Map<Integer, BigDecimal> calculateDynamicFieldsFromSettings(Map<String, Object> settings, BigDecimal inputValue) {
        Map<Integer, BigDecimal> result = new HashMap<>();
        
        Object valueRulesObj = settings.get("valueRules");
        if (!(valueRulesObj instanceof Map)) {
            return result;
        }
        
        Map<String, Object> valueRules = (Map<String, Object>) valueRulesObj;
        Object tiersObj = valueRules.get("tiers");
        if (!(tiersObj instanceof List)) {
            return result;
        }
        
        List<Map<String, Object>> tiers = (List<Map<String, Object>>) tiersObj;
        
        // 查找匹配的tier
        for (Map<String, Object> tier : tiers) {
            Object thresholdObj = tier.get("threshold");
            Object compareTypeObj = tier.get("compareType");
            
            if (thresholdObj == null || compareTypeObj == null) continue;
            
            BigDecimal threshold = new BigDecimal(thresholdObj.toString());
            String compareType = compareTypeObj.toString();
            
            boolean matched = false;
            if ("lte".equals(compareType)) {
                matched = inputValue.compareTo(threshold) <= 0;
            } else if ("lt".equals(compareType)) {
                matched = inputValue.compareTo(threshold) < 0;
            } else if ("gte".equals(compareType)) {
                matched = inputValue.compareTo(threshold) >= 0;
            } else if ("gt".equals(compareType)) {
                matched = inputValue.compareTo(threshold) > 0;
            }
            
            if (matched) {
                Object fieldValuesObj = tier.get("fieldValues");
                if (fieldValuesObj instanceof Map) {
                    Map<String, Object> fv = (Map<String, Object>) fieldValuesObj;
                    for (Map.Entry<String, Object> entry : fv.entrySet()) {
                        try {
                            int fieldIndex = Integer.parseInt(entry.getKey());
                            BigDecimal value = new BigDecimal(entry.getValue().toString());
                            result.put(fieldIndex, value);
                        } catch (NumberFormatException e) {
                            log.warn("无法解析字段值: key={}, value={}", entry.getKey(), entry.getValue());
                        }
                    }
                }
                break;
            }
        }
        
        return result;
    }
}
