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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.yhy.module.core.dal.dataobject.quota.QuotaFeeItemDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateFieldLabelDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaRateItemDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaUnifiedFeeResourceDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaUnifiedFeeSettingDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryTreeDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceCategoryTreeMappingDO;
import com.yhy.module.core.dal.dataobject.workbench.*;
import com.yhy.module.core.dal.mysql.quota.QuotaFeeItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaRateFieldLabelMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaRateItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaUnifiedFeeResourceMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaUnifiedFeeSettingMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryTreeMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceCategoryTreeMappingMapper;
import com.yhy.module.core.dal.mysql.workbench.*;
import com.yhy.module.core.service.workbench.WbSnapshotService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工作台快照服务实现
 *
 * @author yihuiyong
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WbSnapshotServiceImpl implements WbSnapshotService {

    // 后台Mapper
    private final ResourceCategoryTreeMapper resourceCategoryTreeMapper;
    private final ResourceCategoryTreeMappingMapper resourceCategoryTreeMappingMapper;
    private final QuotaRateItemMapper quotaRateItemMapper;
    private final QuotaFeeItemMapper quotaFeeItemMapper;
    private final QuotaUnifiedFeeSettingMapper quotaUnifiedFeeSettingMapper;
    private final QuotaUnifiedFeeResourceMapper quotaUnifiedFeeResourceMapper;
    private final QuotaRateFieldLabelMapper quotaRateFieldLabelMapper;

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createSnapshot(Long compileTreeId, Long quotaCatalogItemId, Long rateModeId) {
        log.info("[createSnapshot] 开始创建快照, compileTreeId={}, quotaCatalogItemId={}, rateModeId={}",
                compileTreeId, quotaCatalogItemId, rateModeId);

        // 1. 复制机类树
        Map<Long, Long> categoryTreeIdMapping = copyCategoryTree(compileTreeId, quotaCatalogItemId);
        log.info("[createSnapshot] 机类树复制完成, 数量={}", categoryTreeIdMapping.size());

        // 2. 复制机类映射
        copyCategoryTreeMapping(compileTreeId, categoryTreeIdMapping);
        log.info("[createSnapshot] 机类映射复制完成");

        // 3. 复制费率模板
        Map<Long, Long> rateItemIdMapping = copyRateItems(compileTreeId, rateModeId);
        log.info("[createSnapshot] 费率模板复制完成, 数量={}", rateItemIdMapping.size());

        // 4. 复制取费模板
        copyFeeItems(compileTreeId, rateModeId, rateItemIdMapping);
        log.info("[createSnapshot] 取费模板复制完成");

        // 5. 复制统一取费设置
        Map<Long, Long> unifiedFeeSettingIdMapping = copyUnifiedFeeSettings(compileTreeId, rateModeId);
        log.info("[createSnapshot] 统一取费设置复制完成, 数量={}", unifiedFeeSettingIdMapping.size());

        // 6. 复制统一取费子目工料机
        copyUnifiedFeeResources(compileTreeId, unifiedFeeSettingIdMapping);
        log.info("[createSnapshot] 统一取费子目工料机复制完成");

        // 7. 复制费率字段标签
        copyRateFieldLabels(compileTreeId, rateModeId);
        log.info("[createSnapshot] 费率字段标签复制完成");

        log.info("[createSnapshot] 快照创建完成, compileTreeId={}", compileTreeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSnapshot(Long compileTreeId) {
        log.info("[deleteSnapshot] 开始删除快照, compileTreeId={}", compileTreeId);

        wbUnifiedFeeResourceMapper.deleteByCompileTreeId(compileTreeId);
        wbUnifiedFeeSettingMapper.deleteByCompileTreeId(compileTreeId);
        wbFeeItemMapper.deleteByCompileTreeId(compileTreeId);
        wbRateItemMapper.deleteByCompileTreeId(compileTreeId);
        wbRateFieldLabelMapper.deleteByCompileTreeId(compileTreeId);
        wbCategoryTreeMappingMapper.deleteByCompileTreeId(compileTreeId);
        wbCategoryTreeMapper.deleteByCompileTreeId(compileTreeId);

        log.info("[deleteSnapshot] 快照删除完成, compileTreeId={}", compileTreeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void switchRateModeSnapshot(Long compileTreeId, Long newRateModeId) {
        log.info("[switchRateModeSnapshot] 切换费率模式快照, compileTreeId={}, newRateModeId={}",
                compileTreeId, newRateModeId);

        // 删除指定费率模式的快照（按 catalogItemId 过滤，保留其他费率模式的快照）
        int deletedRateFieldLabels = wbRateFieldLabelMapper.deleteByCompileTreeIdAndCatalogItemId(compileTreeId, newRateModeId);
        int deletedRateItems = wbRateItemMapper.deleteByCompileTreeIdAndCatalogItemId(compileTreeId, newRateModeId);
        int deletedFeeItems = wbFeeItemMapper.deleteByCompileTreeIdAndCatalogItemId(compileTreeId, newRateModeId);

        // 删除统一取费设置及其关联的工料机（级联删除）
        List<WbUnifiedFeeSettingDO> oldSettings = wbUnifiedFeeSettingMapper.selectByCompileTreeIdAndCatalogItemId(compileTreeId, newRateModeId);
        int deletedUnifiedFeeSettings = wbUnifiedFeeSettingMapper.deleteByCompileTreeIdAndCatalogItemId(compileTreeId, newRateModeId);

        // 删除关联的工料机（通过 unifiedFeeSettingId）
        int deletedUnifiedFeeResources = 0;
        for (WbUnifiedFeeSettingDO setting : oldSettings) {
            List<WbUnifiedFeeResourceDO> resources = wbUnifiedFeeResourceMapper.selectByUnifiedFeeSettingId(setting.getId());
            for (WbUnifiedFeeResourceDO resource : resources) {
                wbUnifiedFeeResourceMapper.deleteById(resource.getId());
                deletedUnifiedFeeResources++;
            }
        }

        log.info("[switchRateModeSnapshot] 删除旧快照完成, rateModeId={}, deletedRateFieldLabels={}, deletedRateItems={}, deletedFeeItems={}, deletedUnifiedFeeSettings={}, deletedUnifiedFeeResources={}",
                newRateModeId, deletedRateFieldLabels, deletedRateItems, deletedFeeItems, deletedUnifiedFeeSettings, deletedUnifiedFeeResources);

        // 复制新费率模式的数据
        Map<Long, Long> rateItemIdMapping = copyRateItems(compileTreeId, newRateModeId);
        copyFeeItems(compileTreeId, newRateModeId, rateItemIdMapping);
        Map<Long, Long> unifiedFeeSettingIdMapping = copyUnifiedFeeSettings(compileTreeId, newRateModeId);
        copyUnifiedFeeResources(compileTreeId, unifiedFeeSettingIdMapping);
        copyRateFieldLabels(compileTreeId, newRateModeId);

        log.info("[switchRateModeSnapshot] 费率模式快照切换完成");
    }

    /**
     * 复制机类树
     * 
     * @return 旧ID → 新ID 映射
     */
    private Map<Long, Long> copyCategoryTree(Long compileTreeId, Long quotaCatalogItemId) {
        Map<Long, Long> idMapping = new HashMap<>();

        // 查询后台机类树（根据定额专业关联的catalogId）
        List<ResourceCategoryTreeDO> sourceList = resourceCategoryTreeMapper.selectByCatalogId(quotaCatalogItemId);
        if (CollUtil.isEmpty(sourceList)) {
            log.warn("[copyCategoryTree] 未找到机类树数据, quotaCatalogItemId={}", quotaCatalogItemId);
            return idMapping;
        }

        for (ResourceCategoryTreeDO source : sourceList) {
            WbCategoryTreeDO target = new WbCategoryTreeDO();
            target.setId(IdUtil.getSnowflakeNextId());
            target.setCompileTreeId(compileTreeId);
            target.setSourceId(source.getId());
            target.setCatalogId(source.getCatalogId());
            target.setParentId(source.getParentId() != null ? idMapping.get(source.getParentId()) : null);
            target.setCode(source.getCode());
            target.setName(source.getName());
            target.setNodeType(source.getNodeType());
            target.setPath(source.getPath());
            target.setSortOrder(source.getSortOrder());
            target.setAttributes(source.getAttributes());

            wbCategoryTreeMapper.insert(target);
            idMapping.put(source.getId(), target.getId());
        }

        return idMapping;
    }

    /**
     * 复制机类映射
     */
    private void copyCategoryTreeMapping(Long compileTreeId, Map<Long, Long> categoryTreeIdMapping) {
        if (categoryTreeIdMapping.isEmpty()) {
            return;
        }

        for (Map.Entry<Long, Long> entry : categoryTreeIdMapping.entrySet()) {
            Long sourceCategoryTreeId = entry.getKey();
            Long targetCategoryTreeId = entry.getValue();

            List<ResourceCategoryTreeMappingDO> mappings = 
                    resourceCategoryTreeMappingMapper.selectByCategoryTreeId(sourceCategoryTreeId);

            for (ResourceCategoryTreeMappingDO source : mappings) {
                WbCategoryTreeMappingDO target = new WbCategoryTreeMappingDO();
                target.setId(IdUtil.getSnowflakeNextId());
                target.setCompileTreeId(compileTreeId);
                target.setSourceId(source.getId());
                target.setCategoryTreeId(targetCategoryTreeId);
                target.setCategoryId(source.getCategoryId());
                target.setSortOrder(source.getSortOrder());

                wbCategoryTreeMappingMapper.insert(target);
            }
        }
    }

    /**
     * 复制费率模板
     * 
     * @return 旧ID → 新ID 映射
     */
    private Map<Long, Long> copyRateItems(Long compileTreeId, Long rateModeId) {
        Map<Long, Long> idMapping = new HashMap<>();

        List<QuotaRateItemDO> sourceList = quotaRateItemMapper.selectListByCatalogItemId(rateModeId);
        if (CollUtil.isEmpty(sourceList)) {
            log.warn("[copyRateItems] 未找到费率模板数据, rateModeId={}", rateModeId);
            return idMapping;
        }

        // 按层级排序，确保父节点先插入
        sourceList.sort((a, b) -> {
            int levelA = a.getLevel() != null ? a.getLevel() : 0;
            int levelB = b.getLevel() != null ? b.getLevel() : 0;
            return Integer.compare(levelA, levelB);
        });

        for (QuotaRateItemDO source : sourceList) {
            WbRateItemDO target = new WbRateItemDO();
            target.setId(IdUtil.getSnowflakeNextId());
            target.setCompileTreeId(compileTreeId);
            target.setSourceId(source.getId());
            target.setCatalogItemId(source.getCatalogItemId());
            target.setParentId(source.getParentId() != null ? idMapping.get(source.getParentId()) : null);
            target.setCustomCode(source.getCustomCode());
            target.setName(source.getName());
            target.setRateCode(source.getRateCode());
            target.setIsEditable(source.getIsEditable());
            target.setDefaultValue(source.getDefaultValue());
            target.setValueMode(source.getValueMode());
            target.setSettings(source.getSettings());
            target.setNodeType(source.getNodeType());
            target.setLevel(source.getLevel());
            target.setSortOrder(source.getSortOrder());

            wbRateItemMapper.insert(target);
            idMapping.put(source.getId(), target.getId());
        }

        return idMapping;
    }

    /**
     * 复制取费模板
     */
    private void copyFeeItems(Long compileTreeId, Long rateModeId, Map<Long, Long> rateItemIdMapping) {
        List<QuotaFeeItemDO> sourceList = quotaFeeItemMapper.selectListByCatalogItemId(rateModeId);
        if (CollUtil.isEmpty(sourceList)) {
            log.warn("[copyFeeItems] 未找到取费模板数据, rateModeId={}", rateModeId);
            return;
        }

        for (QuotaFeeItemDO source : sourceList) {
            WbFeeItemDO target = new WbFeeItemDO();
            target.setId(IdUtil.getSnowflakeNextId());
            target.setCompileTreeId(compileTreeId);
            target.setSourceId(source.getId());
            target.setCatalogItemId(source.getCatalogItemId());
            // 映射rateItemId到新ID
            target.setRateItemId(source.getRateItemId() != null ? 
                    rateItemIdMapping.getOrDefault(source.getRateItemId(), source.getRateItemId()) : null);
            target.setCustomCode(source.getCustomCode());
            target.setName(source.getName());
            target.setCalcBase(source.getCalcBase());
            target.setCode(source.getCode());
            target.setFeeCategory(source.getFeeCategory());
            target.setBaseDescription(source.getBaseDescription());
            target.setSortOrder(source.getSortOrder());
            target.setHidden(source.getHidden());
            target.setVariable(source.getVariable());
            target.setSystemCode(source.getSystemCode());

            wbFeeItemMapper.insert(target);
        }
    }

    /**
     * 复制统一取费设置
     * 
     * @return 旧ID → 新ID 映射
     */
    private Map<Long, Long> copyUnifiedFeeSettings(Long compileTreeId, Long rateModeId) {
        Map<Long, Long> idMapping = new HashMap<>();

        List<QuotaUnifiedFeeSettingDO> sourceList = quotaUnifiedFeeSettingMapper.selectListByCatalogItemId(rateModeId);
        if (CollUtil.isEmpty(sourceList)) {
            log.warn("[copyUnifiedFeeSettings] 未找到统一取费设置数据, rateModeId={}", rateModeId);
            return idMapping;
        }

        // 按parentId排序，确保父节点先插入（null在前）
        sourceList.sort((a, b) -> {
            if (a.getParentId() == null && b.getParentId() == null) return 0;
            if (a.getParentId() == null) return -1;
            if (b.getParentId() == null) return 1;
            return Long.compare(a.getParentId(), b.getParentId());
        });

        for (QuotaUnifiedFeeSettingDO source : sourceList) {
            WbUnifiedFeeSettingDO target = new WbUnifiedFeeSettingDO();
            target.setId(IdUtil.getSnowflakeNextId());
            target.setCompileTreeId(compileTreeId);
            target.setSourceId(source.getId());
            target.setCatalogItemId(source.getCatalogItemId());
            target.setParentId(source.getParentId() != null ? idMapping.get(source.getParentId()) : null);
            target.setCustomCode(source.getCustomCode());
            target.setCode(source.getCode());
            target.setName(source.getName());
            target.setFeeChapter(source.getFeeChapter());
            target.setFeeCategory(source.getFeeCategory());
            target.setThisListPercentage(source.getThisListPercentage());
            target.setSpecifiedListPercentage(source.getSpecifiedListPercentage());
            target.setSpecifiedListCode(source.getSpecifiedListCode());
            target.setNodeType(source.getNodeType());
            target.setUnit(source.getUnit());
            target.setAttributes(source.getAttributes());
            target.setSortOrder(source.getSortOrder());

            wbUnifiedFeeSettingMapper.insert(target);
            idMapping.put(source.getId(), target.getId());
        }

        return idMapping;
    }

    /**
     * 复制统一取费子目工料机
     */
    private void copyUnifiedFeeResources(Long compileTreeId, Map<Long, Long> unifiedFeeSettingIdMapping) {
        if (unifiedFeeSettingIdMapping.isEmpty()) {
            return;
        }

        for (Map.Entry<Long, Long> entry : unifiedFeeSettingIdMapping.entrySet()) {
            Long sourceSettingId = entry.getKey();
            Long targetSettingId = entry.getValue();

            List<QuotaUnifiedFeeResourceDO> resources = 
                    quotaUnifiedFeeResourceMapper.selectListByUnifiedFeeSettingId(sourceSettingId);

            for (QuotaUnifiedFeeResourceDO source : resources) {
                WbUnifiedFeeResourceDO target = new WbUnifiedFeeResourceDO();
                target.setId(IdUtil.getSnowflakeNextId());
                target.setCompileTreeId(compileTreeId);
                target.setSourceId(source.getId());
                target.setUnifiedFeeSettingId(targetSettingId);
                target.setResourceItemId(source.getResourceItemId());
                target.setDosage(source.getDosage());
                target.setAdjustedDosage(source.getAdjustedDosage());
                target.setAttributes(source.getAttributes());
                target.setSortOrder(source.getSortOrder());

                wbUnifiedFeeResourceMapper.insert(target);
            }
        }
    }

    /**
     * 复制费率字段标签
     */
    private void copyRateFieldLabels(Long compileTreeId, Long rateModeId) {
        List<QuotaRateFieldLabelDO> sourceList = quotaRateFieldLabelMapper.selectListByCatalogItemId(rateModeId);
        if (CollUtil.isEmpty(sourceList)) {
            log.warn("[copyRateFieldLabels] 未找到费率字段标签数据, rateModeId={}", rateModeId);
            return;
        }

        for (QuotaRateFieldLabelDO source : sourceList) {
            WbRateFieldLabelDO target = new WbRateFieldLabelDO();
            target.setId(IdUtil.getSnowflakeNextId());
            target.setCompileTreeId(compileTreeId);
            target.setSourceId(source.getId());
            target.setCatalogItemId(source.getCatalogItemId());
            target.setLabelName(source.getLabelName());
            target.setSortOrder(source.getSortOrder());

            wbRateFieldLabelMapper.insert(target);
        }
    }
}
