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

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeSettingRespVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeSettingSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaUnifiedFeeSettingDO;
import com.yhy.module.core.dal.mysql.quota.QuotaUnifiedFeeSettingMapper;
import com.yhy.module.core.enums.ErrorCodeConstants;
import com.yhy.module.core.service.quota.QuotaUnifiedFeeResourceService;
import com.yhy.module.core.service.quota.QuotaUnifiedFeeSettingService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

/**
 * 统一取费设置 Service 实现类
 */
@Service
@Validated
@Slf4j
public class QuotaUnifiedFeeSettingServiceImpl implements QuotaUnifiedFeeSettingService {

    @Resource
    private QuotaUnifiedFeeSettingMapper unifiedFeeSettingMapper;

    @Resource
    @Lazy
    private QuotaUnifiedFeeResourceService unifiedFeeResourceService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUnifiedFeeSetting(QuotaUnifiedFeeSettingSaveReqVO createReqVO) {
        // 设置默认节点类型
        if (createReqVO.getNodeType() == null) {
            createReqVO.setNodeType(createReqVO.getParentId() == null ? 
                QuotaUnifiedFeeSettingDO.NODE_TYPE_PARENT : QuotaUnifiedFeeSettingDO.NODE_TYPE_CHILD);
        }

        // 验证取费章节不能与其他行有交集
        validateFeeChapterNoIntersection(createReqVO.getCatalogItemId(), null, createReqVO.getFeeChapter());

        // 设置排序值
        if (createReqVO.getSortOrder() == null) {
            // 没有指定 sortOrder，追加到末尾
            Integer maxSortOrder = unifiedFeeSettingMapper.selectMaxSortOrder(
                createReqVO.getCatalogItemId(), createReqVO.getParentId());
            createReqVO.setSortOrder(maxSortOrder + 1);
        } else {
            // 指定了 sortOrder，需要将该位置及之后的记录的 sortOrder 都 +1
            unifiedFeeSettingMapper.incrementSortOrderFrom(
                createReqVO.getCatalogItemId(), createReqVO.getParentId(), createReqVO.getSortOrder());
        }

        // 转换并插入
        QuotaUnifiedFeeSettingDO unifiedFeeSetting = BeanUtil.copyProperties(createReqVO, QuotaUnifiedFeeSettingDO.class);
        unifiedFeeSettingMapper.insert(unifiedFeeSetting);
        return unifiedFeeSetting.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUnifiedFeeSetting(QuotaUnifiedFeeSettingSaveReqVO updateReqVO) {
        // 校验存在
        QuotaUnifiedFeeSettingDO existing = validateUnifiedFeeSettingExistsAndGet(updateReqVO.getId());

        // 验证取费章节不能与其他行有交集
        validateFeeChapterNoIntersection(existing.getCatalogItemId(), updateReqVO.getId(), updateReqVO.getFeeChapter());

        // 更新
        QuotaUnifiedFeeSettingDO updateObj = BeanUtil.copyProperties(updateReqVO, QuotaUnifiedFeeSettingDO.class);
        unifiedFeeSettingMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUnifiedFeeSetting(Long id) {
        // 校验存在
        QuotaUnifiedFeeSettingDO unifiedFeeSetting = validateUnifiedFeeSettingExistsAndGet(id);

        // 如果是父定额，需要删除所有子定额及其工料机
        if (unifiedFeeSetting.isParent()) {
            List<QuotaUnifiedFeeSettingDO> children = unifiedFeeSettingMapper.selectChildListByParentId(id);
            for (QuotaUnifiedFeeSettingDO child : children) {
                // 删除子定额的工料机
                unifiedFeeResourceService.deleteByUnifiedFeeSettingId(child.getId());
                // 删除子定额
                unifiedFeeSettingMapper.deleteById(child.getId());
            }
        } else {
            // 如果是子定额，删除其工料机
            unifiedFeeResourceService.deleteByUnifiedFeeSettingId(id);
        }

        // 删除本节点
        unifiedFeeSettingMapper.deleteById(id);
    }

    @Override
    public QuotaUnifiedFeeSettingDO getUnifiedFeeSetting(Long id) {
        return unifiedFeeSettingMapper.selectById(id);
    }

    @Override
    public List<QuotaUnifiedFeeSettingDO> getUnifiedFeeSettingList(Long catalogItemId) {
        return unifiedFeeSettingMapper.selectListByCatalogItemId(catalogItemId);
    }

    @Override
    public List<QuotaUnifiedFeeSettingRespVO> getUnifiedFeeSettingTree(Long catalogItemId) {
        // 获取所有节点
        List<QuotaUnifiedFeeSettingDO> allItems = unifiedFeeSettingMapper.selectListByCatalogItemId(catalogItemId);
        
        // 转换为VO
        List<QuotaUnifiedFeeSettingRespVO> allVOs = allItems.stream()
            .map(item -> BeanUtil.copyProperties(item, QuotaUnifiedFeeSettingRespVO.class))
            .collect(Collectors.toList());

        // 构建树
        return buildTree(allVOs);
    }

    @Override
    public List<QuotaUnifiedFeeSettingDO> getParentList(Long catalogItemId) {
        return unifiedFeeSettingMapper.selectParentListByCatalogItemId(catalogItemId);
    }

    @Override
    public List<QuotaUnifiedFeeSettingRespVO> getParentListWithChildFeeChapters(Long catalogItemId) {
        List<QuotaUnifiedFeeSettingDO> allItems = unifiedFeeSettingMapper.selectListByCatalogItemId(catalogItemId);
        
        // 按parentId分组
        Map<Long, List<QuotaUnifiedFeeSettingDO>> childrenMap = allItems.stream()
            .filter(item -> item.getParentId() != null)
            .collect(Collectors.groupingBy(QuotaUnifiedFeeSettingDO::getParentId));
        
        // 构建树形结构：directory → fee(parent) → sub_fee(child)
        return allItems.stream()
            .filter(item -> item.getParentId() == null) // 一级节点（目录或费用）
            .map(rootItem -> buildTreeNode(rootItem, childrenMap))
            .collect(Collectors.toList());
    }
    
    /**
     * 递归构建树节点，并合并子节点的feeChapter
     */
    private QuotaUnifiedFeeSettingRespVO buildTreeNode(QuotaUnifiedFeeSettingDO item, Map<Long, List<QuotaUnifiedFeeSettingDO>> childrenMap) {
        QuotaUnifiedFeeSettingRespVO vo = BeanUtil.copyProperties(item, QuotaUnifiedFeeSettingRespVO.class);
        
        List<QuotaUnifiedFeeSettingDO> children = childrenMap.get(item.getId());
        if (children != null && !children.isEmpty()) {
            // 递归构建子节点
            List<QuotaUnifiedFeeSettingRespVO> childVOs = children.stream()
                .map(child -> buildTreeNode(child, childrenMap))
                .collect(Collectors.toList());
            vo.setChildren(childVOs);
            
            // 合并所有子孙节点的feeChapter到当前节点
            List<String> allChapters = new ArrayList<>();
            collectFeeChapters(childVOs, allChapters);
            if (!allChapters.isEmpty()) {
                vo.setFeeChapter(cn.hutool.json.JSONUtil.toJsonStr(allChapters));
            }
        }
        return vo;
    }
    
    /**
     * 递归收集所有子孙节点的feeChapter
     */
    private void collectFeeChapters(List<QuotaUnifiedFeeSettingRespVO> nodes, List<String> result) {
        for (QuotaUnifiedFeeSettingRespVO node : nodes) {
            // 收集当前节点的feeChapter
            String fc = node.getFeeChapter();
            if (fc != null && !fc.isEmpty() && !"[]".equals(fc)) {
                try {
                    List<String> ids = cn.hutool.json.JSONUtil.toList(fc, String.class);
                    result.addAll(ids);
                } catch (Exception e) {
                    log.warn("解析feeChapter失败: {}", fc);
                }
            }
            // 递归收集子节点
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                collectFeeChapters(node.getChildren(), result);
            }
        }
    }

    @Override
    public List<QuotaUnifiedFeeSettingDO> getChildList(Long parentId) {
        return unifiedFeeSettingMapper.selectChildListByParentId(parentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSort(Long nodeId1, Long nodeId2) {
        QuotaUnifiedFeeSettingDO node1 = validateUnifiedFeeSettingExistsAndGet(nodeId1);
        QuotaUnifiedFeeSettingDO node2 = validateUnifiedFeeSettingExistsAndGet(nodeId2);

        // 交换排序值
        Integer tempSort = node1.getSortOrder();
        node1.setSortOrder(node2.getSortOrder());
        node2.setSortOrder(tempSort);

        unifiedFeeSettingMapper.updateById(node1);
        unifiedFeeSettingMapper.updateById(node2);
    }

    @Override
    public void validateUnifiedFeeSettingExists(Long id) {
        if (unifiedFeeSettingMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_SETTING_NOT_EXISTS);
        }
    }

    private QuotaUnifiedFeeSettingDO validateUnifiedFeeSettingExistsAndGet(Long id) {
        QuotaUnifiedFeeSettingDO unifiedFeeSetting = unifiedFeeSettingMapper.selectById(id);
        if (unifiedFeeSetting == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_SETTING_NOT_EXISTS);
        }
        return unifiedFeeSetting;
    }

    /**
     * 验证取费章节不能与其他行有交集
     * @param catalogItemId 模式节点ID
     * @param excludeId 排除的ID（更新时排除自身）
     * @param feeChapter 取费章节JSON数组字符串
     */
    private void validateFeeChapterNoIntersection(Long catalogItemId, Long excludeId, String feeChapter) {
        if (feeChapter == null || feeChapter.isEmpty() || "[]".equals(feeChapter)) {
            return;
        }
        
        // 解析当前的取费章节ID列表
        List<String> currentIds;
        try {
            currentIds = cn.hutool.json.JSONUtil.toList(feeChapter, String.class);
        } catch (Exception e) {
            return; // 解析失败则跳过验证
        }
        
        if (currentIds == null || currentIds.isEmpty()) {
            return;
        }
        
        // 获取同一模式节点下的所有设置
        List<QuotaUnifiedFeeSettingDO> allSettings = unifiedFeeSettingMapper.selectListByCatalogItemId(catalogItemId);
        
        for (QuotaUnifiedFeeSettingDO setting : allSettings) {
            // 排除自身
            if (excludeId != null && excludeId.equals(setting.getId())) {
                continue;
            }
            
            String existingFeeChapter = setting.getFeeChapter();
            if (existingFeeChapter == null || existingFeeChapter.isEmpty() || "[]".equals(existingFeeChapter)) {
                continue;
            }
            
            try {
                List<String> existingIds = cn.hutool.json.JSONUtil.toList(existingFeeChapter, String.class);
                if (existingIds == null || existingIds.isEmpty()) {
                    continue;
                }
                
                // 检查交集
                for (String id : currentIds) {
                    if (existingIds.contains(id)) {
                        throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_CHAPTER_INTERSECTION,
                            setting.getName() != null ? setting.getName() : setting.getCode());
                    }
                }
            } catch (cn.iocoder.yudao.framework.common.exception.ServiceException e) {
                throw e; // 重新抛出业务异常
            } catch (Exception e) {
                // 解析失败则跳过
            }
        }
    }

    private List<QuotaUnifiedFeeSettingRespVO> buildTree(List<QuotaUnifiedFeeSettingRespVO> allVOs) {
        // 按parentId分组
        Map<Long, List<QuotaUnifiedFeeSettingRespVO>> childrenMap = allVOs.stream()
            .filter(vo -> vo.getParentId() != null)
            .collect(Collectors.groupingBy(QuotaUnifiedFeeSettingRespVO::getParentId));

        // 设置子节点
        for (QuotaUnifiedFeeSettingRespVO vo : allVOs) {
            List<QuotaUnifiedFeeSettingRespVO> children = childrenMap.get(vo.getId());
            vo.setChildren(children != null ? children : new ArrayList<>());
            vo.setHasChildren(children != null && !children.isEmpty());
        }

        // 返回根节点列表
        return allVOs.stream()
            .filter(vo -> vo.getParentId() == null)
            .collect(Collectors.toList());
    }
}
