package com.yhy.module.core.service.workbench.impl;

import cn.hutool.core.collection.CollUtil;
import com.yhy.module.core.dal.dataobject.quota.QuotaFeeItemDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateItemDO;
import com.yhy.module.core.dal.dataobject.workbench.WbCategoryTreeDO;
import com.yhy.module.core.dal.dataobject.workbench.WbCategoryTreeMappingDO;
import com.yhy.module.core.dal.dataobject.workbench.WbFeeItemDO;
import com.yhy.module.core.dal.dataobject.workbench.WbRateFieldLabelDO;
import com.yhy.module.core.dal.dataobject.workbench.WbRateItemDO;
import com.yhy.module.core.dal.dataobject.workbench.WbUnifiedFeeResourceDO;
import com.yhy.module.core.dal.dataobject.workbench.WbUnifiedFeeSettingDO;
import com.yhy.module.core.dal.mysql.workbench.WbCategoryTreeMapper;
import com.yhy.module.core.dal.mysql.workbench.WbCategoryTreeMappingMapper;
import com.yhy.module.core.dal.mysql.workbench.WbFeeItemMapper;
import com.yhy.module.core.dal.mysql.workbench.WbRateFieldLabelMapper;
import com.yhy.module.core.dal.mysql.workbench.WbRateItemMapper;
import com.yhy.module.core.dal.mysql.workbench.WbUnifiedFeeResourceMapper;
import com.yhy.module.core.dal.mysql.workbench.WbUnifiedFeeSettingMapper;
import com.yhy.module.core.service.quota.QuotaFeeItemService;
import com.yhy.module.core.service.workbench.WbSnapshotReadService;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

/**
 * 工作台快照读取服务实现
 *
 * @author yihuiyong
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WbSnapshotReadServiceImpl implements WbSnapshotReadService {

    // 快照Mapper
    private final WbRateItemMapper wbRateItemMapper;
    private final WbFeeItemMapper wbFeeItemMapper;
    private final WbUnifiedFeeSettingMapper wbUnifiedFeeSettingMapper;
    private final WbUnifiedFeeResourceMapper wbUnifiedFeeResourceMapper;
    private final WbCategoryTreeMapper wbCategoryTreeMapper;
    private final WbCategoryTreeMappingMapper wbCategoryTreeMappingMapper;
    private final WbRateFieldLabelMapper wbRateFieldLabelMapper;

    // 后台Service（用于复用树构建逻辑）
    @Lazy
    private final QuotaFeeItemService quotaFeeItemService;

    @Override
    public List<WbRateItemDO> getRateItems(Long compileTreeId, Long rateModeId) {
        // 只从快照表读取，不回退到后台标准库
        // 按 rateModeId（catalogItemId）过滤，避免多定额专业数据混合返回
        List<WbRateItemDO> snapshotItems;
        if (rateModeId != null) {
            snapshotItems = wbRateItemMapper.selectByCompileTreeIdAndCatalogItemId(compileTreeId, rateModeId);
        } else {
            snapshotItems = wbRateItemMapper.selectByCompileTreeId(compileTreeId);
        }
        if (CollUtil.isNotEmpty(snapshotItems)) {
            log.debug("[getRateItems] 从快照表读取费率模板, compileTreeId={}, rateModeId={}, count={}", compileTreeId, rateModeId, snapshotItems.size());
            return snapshotItems;
        }

        log.warn("[getRateItems] 快照不存在, compileTreeId={}, rateModeId={}", compileTreeId, rateModeId);
        return new ArrayList<>();
    }

    @Override
    public List<WbFeeItemDO> getFeeItems(Long compileTreeId, Long rateModeId) {
        // 只从快照表读取，不回退到后台标准库
        // 按 rateModeId（catalogItemId）过滤，避免多定额专业数据混合返回
        List<WbFeeItemDO> snapshotItems;
        if (rateModeId != null) {
            snapshotItems = wbFeeItemMapper.selectByCompileTreeIdAndCatalogItemId(compileTreeId, rateModeId);
        } else {
            snapshotItems = wbFeeItemMapper.selectByCompileTreeId(compileTreeId);
        }
        if (CollUtil.isNotEmpty(snapshotItems)) {
            log.debug("[getFeeItems] 从快照表读取取费模板, compileTreeId={}, rateModeId={}, count={}", compileTreeId, rateModeId, snapshotItems.size());
            return snapshotItems;
        }

        log.warn("[getFeeItems] 快照不存在, compileTreeId={}, rateModeId={}", compileTreeId, rateModeId);
        return new ArrayList<>();
    }

    @Override
    public List<WbUnifiedFeeSettingDO> getUnifiedFeeSettings(Long compileTreeId, Long rateModeId) {
        // 只从快照表读取，不回退到后台标准库
        // 使用 catalogItemId（即 rateModeId）过滤，确保切换定额专业时返回对应费率模式的数据
        List<WbUnifiedFeeSettingDO> snapshotItems;
        if (rateModeId != null) {
            snapshotItems = wbUnifiedFeeSettingMapper.selectByCompileTreeIdAndCatalogItemId(compileTreeId, rateModeId);
        } else {
            snapshotItems = wbUnifiedFeeSettingMapper.selectByCompileTreeId(compileTreeId);
        }
        if (CollUtil.isNotEmpty(snapshotItems)) {
            log.debug("[getUnifiedFeeSettings] 从快照表读取统一取费设置, compileTreeId={}, rateModeId={}, count={}", compileTreeId, rateModeId, snapshotItems.size());
            return snapshotItems;
        }

        log.warn("[getUnifiedFeeSettings] 快照不存在, compileTreeId={}, rateModeId={}", compileTreeId, rateModeId);
        return new ArrayList<>();
    }

    @Override
    public List<WbUnifiedFeeResourceDO> getUnifiedFeeResources(Long compileTreeId, Long unifiedFeeSettingId) {
        // 从快照表读取
        return wbUnifiedFeeResourceMapper.selectByUnifiedFeeSettingId(unifiedFeeSettingId);
    }

    @Override
    public List<WbCategoryTreeDO> getCategoryTree(Long compileTreeId, Long quotaCatalogItemId) {
        // 只从快照表读取，不回退到后台标准库
        List<WbCategoryTreeDO> snapshotItems = wbCategoryTreeMapper.selectByCompileTreeId(compileTreeId);
        if (CollUtil.isNotEmpty(snapshotItems)) {
            log.debug("[getCategoryTree] 从快照表读取机类树, compileTreeId={}, count={}", compileTreeId, snapshotItems.size());
            return snapshotItems;
        }

        log.warn("[getCategoryTree] 快照不存在, compileTreeId={}", compileTreeId);
        return new ArrayList<>();
    }

    @Override
    public List<WbCategoryTreeMappingDO> getCategoryTreeMappings(Long compileTreeId, Long categoryTreeId) {
        // 从快照表读取
        return wbCategoryTreeMappingMapper.selectByCategoryTreeId(categoryTreeId);
    }

    @Override
    public boolean hasSnapshot(Long compileTreeId) {
        // 检查是否有费率模板快照（作为快照存在的标志）
        List<WbRateItemDO> items = wbRateItemMapper.selectByCompileTreeId(compileTreeId);
        return CollUtil.isNotEmpty(items);
    }

    @Override
    public WbRateItemDO getRateItemById(Long compileTreeId, Long snapshotRateItemId) {
        return wbRateItemMapper.selectById(snapshotRateItemId);
    }

    // ==================== 转换方法 ====================

    // ==================== 快照到Quota的转换方法（用于复用后台标准库逻辑） ====================

    @Override
    public List<com.yhy.module.core.controller.admin.quota.vo.QuotaFeeItemWithRateRespVO> getFeeItemWithRateTree(Long compileTreeId, Long rateModeId) {
        // 1. 检查是否有快照
        if (!hasSnapshot(compileTreeId)) {
            log.debug("[getFeeItemWithRateTree] 快照不存在，返回null让调用方使用后台标准库, compileTreeId={}", compileTreeId);
            return null;
        }

        // 2. 从快照表读取费率项和取费项（使用 rateModeId 过滤）
        List<WbRateItemDO> allRateItems;
        List<WbFeeItemDO> wbFeeItems;

        if (rateModeId != null) {
            // 按费率模式ID过滤
            allRateItems = wbRateItemMapper.selectByCompileTreeIdAndCatalogItemId(compileTreeId, rateModeId);
            wbFeeItems = wbFeeItemMapper.selectByCompileTreeIdAndCatalogItemId(compileTreeId, rateModeId);
            log.debug("[getFeeItemWithRateTree] 使用rateModeId过滤, compileTreeId={}, rateModeId={}", compileTreeId, rateModeId);
        } else {
            // 不过滤，返回所有数据
            allRateItems = wbRateItemMapper.selectByCompileTreeId(compileTreeId);
            wbFeeItems = wbFeeItemMapper.selectByCompileTreeId(compileTreeId);
            log.debug("[getFeeItemWithRateTree] 未指定rateModeId，返回所有数据, compileTreeId={}", compileTreeId);
        }

        if (CollUtil.isEmpty(allRateItems)) {
            log.debug("[getFeeItemWithRateTree] 快照费率项为空, compileTreeId={}, rateModeId={}", compileTreeId, rateModeId);
            return null;
        }

        // 3. 过滤只保留目录节点（与后台标准库API保持一致）
        List<WbRateItemDO> wbRateItems = allRateItems.stream()
                .filter(r -> "directory".equals(r.getNodeType()))
                .collect(Collectors.toList());

        // 4. 转换为QuotaRateItemDO和QuotaFeeItemDO，复用后台标准库的逻辑
        List<QuotaRateItemDO> rateItems = wbRateItems.stream()
                .map(this::convertToQuotaRateItemDO)
                .collect(Collectors.toList());

        List<QuotaFeeItemDO> feeItems = wbFeeItems.stream()
                .map(this::convertToQuotaFeeItemDO)
                .collect(Collectors.toList());

        // 5. 调用公共方法构建结果（复用后台标准库的逻辑）
        log.debug("[getFeeItemWithRateTree] 从快照构建取费项树, compileTreeId={}, rateModeId={}, rateItemCount={}, feeItemCount={}",
                compileTreeId, rateModeId, rateItems.size(), feeItems.size());
        return quotaFeeItemService.buildFeeItemWithRateList(rateItems, feeItems, rateModeId);
    }

    /**
     * 将WbRateItemDO转换为QuotaRateItemDO
     */
    private QuotaRateItemDO convertToQuotaRateItemDO(WbRateItemDO wb) {
        QuotaRateItemDO quota = new QuotaRateItemDO();
        quota.setId(wb.getId());
        quota.setCatalogItemId(wb.getCatalogItemId());
        quota.setParentId(wb.getParentId());
        quota.setCustomCode(wb.getCustomCode());
        quota.setName(wb.getName());
        quota.setRateCode(wb.getRateCode());
        quota.setIsEditable(wb.getIsEditable());
        quota.setDefaultValue(wb.getDefaultValue());
        quota.setValueMode(wb.getValueMode());
        quota.setSettings(wb.getSettings());
        quota.setNodeType(wb.getNodeType());
        quota.setLevel(wb.getLevel());
        quota.setSortOrder(wb.getSortOrder());
        return quota;
    }

    /**
     * 将WbFeeItemDO转换为QuotaFeeItemDO
     */
    private QuotaFeeItemDO convertToQuotaFeeItemDO(WbFeeItemDO wb) {
        QuotaFeeItemDO quota = new QuotaFeeItemDO();
        quota.setId(wb.getId());
        quota.setCatalogItemId(wb.getCatalogItemId());
        quota.setRateItemId(wb.getRateItemId());
        quota.setName(wb.getName());
        quota.setCustomCode(wb.getCustomCode());
        quota.setCalcBase(wb.getCalcBase());
        quota.setCode(wb.getCode());
        quota.setFeeCategory(wb.getFeeCategory());
        quota.setBaseDescription(wb.getBaseDescription());
        quota.setSortOrder(wb.getSortOrder());
        quota.setHidden(wb.getHidden());
        quota.setVariable(wb.getVariable());
        quota.setSystemCode(wb.getSystemCode());
        return quota;
    }

    @Override
    public List<WbRateFieldLabelDO> getRateFieldLabels(Long compileTreeId, Long rateModeId) {
        if (compileTreeId == null || rateModeId == null) {
            return null;
        }
        
        List<WbRateFieldLabelDO> labels = wbRateFieldLabelMapper.selectByCompileTreeIdAndCatalogItemId(compileTreeId, rateModeId);
        if (CollUtil.isEmpty(labels)) {
            return null;
        }
        return labels;
    }
}
