package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import shop.alien.entity.result.R;
import shop.alien.entity.store.StoreDictionary;
import shop.alien.entity.store.excelVo.DictionaryLibraryExcelVo;
import shop.alien.entity.store.excelVo.util.ExcelHeader;
import shop.alien.mapper.StoreDictionaryMapper;
import shop.alien.store.service.DictOpinionFeedbackService;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 意见反馈字典管理ServiceImpl
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DictOpinionFeedbackServiceImpl extends ServiceImpl<StoreDictionaryMapper, StoreDictionary> implements DictOpinionFeedbackService {

    private static final String DEFAULT_TYPE_NAME = "dict_opinion_feedback";

    private final StoreDictionaryMapper storeDictionaryMapper;

    /**
     * 查询意见反馈字典（三级树形结构）
     * 如果传入dictDetail，则查询匹配的记录及其父级和子级树形结构
     * 如果不传dictDetail，则返回完整的字典库树形结构
     *
     * @param dictDetail 字典描述（可选），如果传入则根据此参数过滤
     * @return 字典树形结构列表
     */
    @Override
    public List<StoreDictionary> queryDictOpinionFeedbackTree(String dictDetail) {
        // 如果传入了dictDetail，使用过滤逻辑
        if (StringUtils.isNotBlank(dictDetail)) {
            return selectDictBydictDetail(dictDetail);
        }
        
        // 否则使用原有逻辑：查询所有意见反馈字典数据
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
        queryWrapper.orderByAsc(StoreDictionary::getSortId);
        List<StoreDictionary> dictList = storeDictionaryMapper.selectList(queryWrapper);

        return buildTreeOptimized(dictList);
    }
    
    /**
     * 根据dictDetail查询意见反馈字典（包含父级或子级树形结构）
     * 支持查询多个同名数据及其父级和子级
     *
     * @param dictDetail 字典描述
     * @return 意见反馈字典树形结构列表
     */
    private List<StoreDictionary> selectDictBydictDetail(String dictDetail) {
        if (StringUtils.isBlank(dictDetail)) {
            throw new IllegalArgumentException("dictDetail不能为空");
        }

        // 通过dictDetail模糊查询所有匹配的记录（可能有多个同名数据）
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
        queryWrapper.like(StoreDictionary::getDictDetail, dictDetail);
        
        List<StoreDictionary> matchedDicts = storeDictionaryMapper.selectList(queryWrapper);
        
        if (matchedDicts == null || matchedDicts.isEmpty()) {
            log.warn("未找到dictDetail为[{}]的记录", dictDetail);
            return new ArrayList<>();
        }

        log.info("找到{}条dictDetail为[{}]的记录", matchedDicts.size(), dictDetail);

        // 用于存储每个根节点对应的所有节点（按根节点分组）
        Map<Integer, Set<Integer>> rootToNodeIdsMap = new HashMap<>();
        
        // 遍历所有匹配的记录，收集相关节点ID
        for (StoreDictionary currentDict : matchedDicts) {
            Integer parentId = currentDict.getParentId();
            Integer rootId;
            
            if (parentId != null && parentId != 0) {
                // 如果有父级，查找根节点
                rootId = findRootId(currentDict.getId());
                log.info("记录ID[{}]有父级[{}], 根节点ID[{}]", currentDict.getId(), parentId, rootId);
                
                // 收集从根节点到当前节点的路径上的所有节点ID
                List<Integer> pathNodeIds = new ArrayList<>();
                collectPathNodes(currentDict.getId(), pathNodeIds);
                log.info("路径节点IDs: {}", pathNodeIds);
                
                // 收集该根节点下的所有相关节点ID（包括路径节点及其所有子节点）
                Set<Integer> nodeIds = rootToNodeIdsMap.computeIfAbsent(rootId, k -> new HashSet<>());
                for (Integer nodeId : pathNodeIds) {
                    nodeIds.add(nodeId);
                    collectChildrenIds(nodeId, nodeIds);
                }
            } else {
                // 如果没有父级，以当前节点为根
                rootId = currentDict.getId();
                log.info("记录ID[{}]没有父级, 作为根节点", currentDict.getId());
                
                // 收集该根节点下的所有相关节点ID
                Set<Integer> nodeIds = rootToNodeIdsMap.computeIfAbsent(rootId, k -> new HashSet<>());
                nodeIds.add(currentDict.getId());
                collectChildrenIds(currentDict.getId(), nodeIds);
            }
        }
        
        // 收集所有需要返回的节点数据
        Map<Integer, StoreDictionary> allNodeMap = new HashMap<>();
        for (Set<Integer> nodeIds : rootToNodeIdsMap.values()) {
            for (Integer nodeId : nodeIds) {
                if (!allNodeMap.containsKey(nodeId)) {
                    StoreDictionary node = storeDictionaryMapper.selectById(nodeId);
                    if (node != null && node.getDeleteFlag() == 0) {
                        allNodeMap.put(nodeId, node);
                    }
                }
            }
        }
        
        log.info("总共收集到{}个节点", allNodeMap.size());
        
        // 构建树形结构，为每个唯一的根节点构建一棵树
        List<StoreDictionary> resultList = new ArrayList<>();
        
        for (Map.Entry<Integer, Set<Integer>> entry : rootToNodeIdsMap.entrySet()) {
            Integer rootId = entry.getKey();
            Set<Integer> nodeIds = entry.getValue();
            
            log.info("处理根节点[{}], 包含{}个节点", rootId, nodeIds.size());
            
            // 从所有节点中筛选出该根节点下的相关节点
            List<StoreDictionary> relatedNodes = new ArrayList<>();
            for (Integer nodeId : nodeIds) {
                StoreDictionary node = allNodeMap.get(nodeId);
                if (node != null) {
                    relatedNodes.add(node);
                }
            }
            
            log.info("根节点[{}]筛选出{}个相关节点", rootId, relatedNodes.size());
            
            // 如果找到相关节点，构建树形结构
            if (!relatedNodes.isEmpty()) {
                StoreDictionary root = buildTreeFromNodeList(relatedNodes, rootId);
                if (root != null) {
                    resultList.add(root);
                    log.info("成功构建根节点[{}]的树形结构", rootId);
                } else {
                    log.warn("构建根节点[{}]的树形结构失败", rootId);
                }
            } else {
                log.warn("根节点[{}]没有相关节点", rootId);
            }
        }
        
        log.info("最终返回{}棵树", resultList.size());
        return resultList;
    }
    
    /**
     * 收集节点的所有子节点ID（递归）
     *
     * @param nodeId 节点ID
     * @param childrenIds 子节点ID集合
     */
    private void collectChildrenIds(Integer nodeId, Set<Integer> childrenIds) {
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
        queryWrapper.eq(StoreDictionary::getParentId, nodeId);
        
        List<StoreDictionary> children = storeDictionaryMapper.selectList(queryWrapper);
        
        if (children != null && !children.isEmpty()) {
            for (StoreDictionary child : children) {
                if (!childrenIds.contains(child.getId())) {
                    childrenIds.add(child.getId());
                    collectChildrenIds(child.getId(), childrenIds);
                }
            }
        }
    }

    /**
     * 递归查找根节点ID
     *
     * @param id 当前节点ID
     * @return 根节点ID
     */
    private Integer findRootId(Integer id) {
        StoreDictionary dict = storeDictionaryMapper.selectById(id);
        if (dict == null || dict.getDeleteFlag() == 1) {
            // 如果节点不存在或已删除，返回当前ID作为根节点
            return id;
        }
        
        Integer parentId = dict.getParentId();
        if (parentId == null || parentId == 0) {
            return id;
        }
        
        return findRootId(parentId);
    }

    /**
     * 收集从当前节点到根节点的路径上的所有节点ID
     *
     * @param nodeId 当前节点ID
     * @param pathNodeIds 路径节点ID列表
     */
    private void collectPathNodes(Integer nodeId, List<Integer> pathNodeIds) {
        StoreDictionary dict = storeDictionaryMapper.selectById(nodeId);
        if (dict == null || dict.getDeleteFlag() == 1) {
            return;
        }
        
        // 避免重复添加
        if (!pathNodeIds.contains(nodeId)) {
            pathNodeIds.add(nodeId);
        }
        
        Integer parentId = dict.getParentId();
        if (parentId != null && parentId != 0) {
            collectPathNodes(parentId, pathNodeIds);
        }
    }

    /**
     * 从节点列表构建树形结构
     *
     * @param nodeList 节点列表
     * @param rootId 根节点ID
     * @return 根节点
     */
    private StoreDictionary buildTreeFromNodeList(List<StoreDictionary> nodeList, Integer rootId) {
        // 创建ID到节点的映射
        Map<Integer, StoreDictionary> nodeMap = new HashMap<>();
        for (StoreDictionary node : nodeList) {
            nodeMap.put(node.getId(), node);
            node.setStoreDictionaryList(new ArrayList<>());
        }
        
        // 找到根节点
        StoreDictionary root = nodeMap.get(rootId);
        if (root == null) {
            return null;
        }
        
        // 建立父子关系
        for (StoreDictionary node : nodeList) {
            if (node.getId().equals(rootId)) {
                continue; // 跳过根节点
            }
            
            Integer parentId = node.getParentId();
            if (parentId != null && parentId != 0) {
                StoreDictionary parent = nodeMap.get(parentId);
                if (parent != null) {
                    parent.getStoreDictionaryList().add(node);
                }
            }
        }
        
        // 对子节点列表按sortId排序
        sortChildren(root);
        
        return root;
    }

    /**
     * 递归排序子节点
     *
     * @param node 节点
     */
    private void sortChildren(StoreDictionary node) {
        if (node == null || node.getStoreDictionaryList() == null) {
            return;
        }
        
        node.getStoreDictionaryList().sort((a, b) -> {
            Integer sortIdA = a.getSortId() != null ? a.getSortId() : 0;
            Integer sortIdB = b.getSortId() != null ? b.getSortId() : 0;
            return sortIdA.compareTo(sortIdB);
        });
        
        // 递归排序所有子节点
        for (StoreDictionary child : node.getStoreDictionaryList()) {
            sortChildren(child);
        }
    }

    /**
     * 构建树形结构（优化版）
     */
    private List<StoreDictionary> buildTreeOptimized(List<StoreDictionary> flatList) {
        if (flatList == null || flatList.isEmpty()) {
            return new ArrayList<>();
        }

        Map<Integer, StoreDictionary> nodeMap = new HashMap<>();
        Map<Integer, List<StoreDictionary>> parentChildMap = new HashMap<>();
        List<StoreDictionary> result = new ArrayList<>();

        for (StoreDictionary entity : flatList) {
            Integer id = entity.getId();
            Integer parentId = entity.getParentId();

            nodeMap.put(id, entity);
            entity.setStoreDictionaryList(new ArrayList<>());

            if (parentId == null || parentId == 0) {
                result.add(entity);
            } else {
                parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(entity);
            }
        }

        for (StoreDictionary entity : flatList) {
            Integer id = entity.getId();
            if (parentChildMap.containsKey(id)) {
                entity.getStoreDictionaryList().addAll(parentChildMap.get(id));
            }
        }

        return result;
    }

    /**
     * 新增意见反馈字典（支持一级、二级、三级）
     */
    @Override
    public boolean addDictOpinionFeedback(StoreDictionary storeDictionary) {
        if (storeDictionary == null || StringUtils.isBlank(storeDictionary.getDictDetail())) {
            throw new IllegalArgumentException("字典描述不能为空");
        }

        storeDictionary.setDeleteFlag(0);
        storeDictionary.setCreatedTime(new Date());

        Integer parentId = storeDictionary.getParentId();
        if (parentId == null) {
            parentId = 0;
        }

        if (parentId != 0) {
            StoreDictionary parent = storeDictionaryMapper.selectById(parentId);
            if (parent == null || parent.getDeleteFlag() == 1) {
                throw new IllegalArgumentException("父节点不存在或已删除");
            }
        }

        String typeName = storeDictionary.getTypeName();
        if (StringUtils.isBlank(typeName)) {
            throw new IllegalArgumentException("typeName不能为空");
        }

        String maxDictId = getMaxDictIdByTypeName(typeName);
        int nextDictId = (maxDictId == null ? 1 : Integer.parseInt(maxDictId)) + 1;
        storeDictionary.setDictId(String.valueOf(nextDictId));

        Integer maxSortId = getMaxSortIdByParentId(parentId);
        storeDictionary.setSortId(maxSortId == null ? 1 : maxSortId + 1);

        return this.save(storeDictionary);
    }

    /**
     * 修改意见反馈字典（支持一级、二级、三级）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDictOpinionFeedback(StoreDictionary storeDictionary) {
        if (storeDictionary == null || storeDictionary.getId() == null) {
            throw new IllegalArgumentException("ID不能为空");
        }
        if (StringUtils.isBlank(storeDictionary.getDictDetail())) {
            throw new IllegalArgumentException("字典描述不能为空");
        }

        StoreDictionary existing = storeDictionaryMapper.selectById(storeDictionary.getId());
        if (existing == null) {
            throw new IllegalArgumentException("记录不存在");
        }
        if (existing.getDeleteFlag() == 1) {
            throw new IllegalArgumentException("该记录已删除");
        }

        Integer existingParentId = existing.getParentId();
        boolean isFirstLevel = (existingParentId == null || existingParentId == 0);
        boolean isSecondLevel = false;

        if (!isFirstLevel) {
            StoreDictionary parent = storeDictionaryMapper.selectById(existingParentId);
            if (parent != null) {
                Integer grandParentId = parent.getParentId();
                isSecondLevel = (grandParentId == null || grandParentId == 0);
            }
        }

        Integer parentId = storeDictionary.getParentId();
        if (parentId == null) {
            parentId = 0;
        }

        Integer normalizedParentId = parentId == null ? 0 : parentId;
        Integer normalizedExistingParentId = existingParentId == null ? 0 : existingParentId;
        Integer oldSortId = existing.getSortId();
        Integer newSortId = storeDictionary.getSortId();
        boolean parentIdChanged = !normalizedParentId.equals(normalizedExistingParentId);

        // 判断是否修改了关键字段（parent_id）
        boolean keyFieldChanged = parentIdChanged;

        if ((isFirstLevel || isSecondLevel) && keyFieldChanged) {
            boolean hasChildren = hasUndeletedChildren(existing.getId());
            if (hasChildren) {
                throw new IllegalArgumentException("该节点存在未删除的子节点，不允许修改关键字段（父节点）");
            }
        }

        if (parentIdChanged) {
            if (parentId != 0) {
                StoreDictionary parent = storeDictionaryMapper.selectById(parentId);
                if (parent == null || parent.getDeleteFlag() == 1) {
                    throw new IllegalArgumentException("父节点不存在或已删除");
                }
            }

            if (newSortId == null) {
                Integer maxSortId = getMaxSortIdByParentId(parentId);
                int nextSortId = (maxSortId == null ? 1 : maxSortId) + 1;
                newSortId = nextSortId;
                storeDictionary.setSortId(newSortId);
            }

            adjustSortOrderForMoveOut(existing.getId(), normalizedExistingParentId, oldSortId);

            if (newSortId != null) {
                try {
                    int newOrder = newSortId;
                    Integer maxSortId = getMaxSortIdByParentId(parentId);
                    int maxOrder = (maxSortId == null ? 0 : maxSortId);
                    if (newOrder <= maxOrder) {
                        adjustSortOrderForMoveIn(existing.getId(), normalizedParentId, newSortId);
                    }
                } catch (NumberFormatException e) {
                    log.warn("无法解析新sortId: {}", newSortId, e);
                }
            }
        }

        Integer oldHidden = existing.getHidden();
        Integer newHidden = storeDictionary.getHidden() == null ? oldHidden : storeDictionary.getHidden();
        storeDictionary.setHidden(newHidden);
        storeDictionary.setDeleteFlag(existing.getDeleteFlag());
        storeDictionary.setCreatedTime(existing.getCreatedTime());
        storeDictionary.setCreatedUserId(existing.getCreatedUserId());
        storeDictionary.setUpdatedTime(new Date());

        if (!parentIdChanged) {
            if (newSortId == null) {
                storeDictionary.setSortId(oldSortId);
            } else if (!newSortId.equals(oldSortId)) {
                adjustSortOrder(existing.getId(), normalizedParentId, oldSortId, newSortId);
            }
        }

        boolean updateResult = this.updateById(storeDictionary);

        boolean hiddenChanged = (oldHidden == null && newHidden != null) ||
                (oldHidden != null && !oldHidden.equals(newHidden));
        if (updateResult && (isFirstLevel || isSecondLevel) && hiddenChanged && newHidden != null) {
            updateChildrenHidden(existing.getId(), newHidden);
        }

        return updateResult;
    }

    /**
     * 判断节点是否有未删除的子节点
     */
    private boolean hasUndeletedChildren(Integer parentId) {
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
        queryWrapper.eq(StoreDictionary::getParentId, parentId);
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
        queryWrapper.last("LIMIT 1");

        StoreDictionary child = storeDictionaryMapper.selectOne(queryWrapper);
        return child != null;
    }

    /**
     * 递归更新子节点的显示/隐藏状态
     */
    private void updateChildrenHidden(Integer parentId, Integer hidden) {
        if (parentId == null || hidden == null) {
            return;
        }

        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
        queryWrapper.eq(StoreDictionary::getParentId, parentId);
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);

        List<StoreDictionary> children = storeDictionaryMapper.selectList(queryWrapper);

        if (children == null || children.isEmpty()) {
            return;
        }

        Date updateTime = new Date();
        for (StoreDictionary child : children) {
            child.setHidden(hidden);
            child.setUpdatedTime(updateTime);
            storeDictionaryMapper.updateById(child);
            updateChildrenHidden(child.getId(), hidden);
        }
    }

    /**
     * 根据 typeName 获取最大 dict_id
     */
    private String getMaxDictIdByTypeName(String typeName) {
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StoreDictionary::getTypeName, typeName);
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);

        queryWrapper.orderByDesc(StoreDictionary::getDictId);
        queryWrapper.last("LIMIT 1");

        StoreDictionary maxDict = storeDictionaryMapper.selectOne(queryWrapper);
        return maxDict != null ? maxDict.getDictId() : null;
    }

    /**
     * 根据parentId获取最大的sortId
     */
    private Integer getMaxSortIdByParentId(Integer parentId) {
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);

        if (parentId == null || parentId == 0) {
            queryWrapper.and(wrapper -> wrapper.isNull(StoreDictionary::getParentId)
                    .or().eq(StoreDictionary::getParentId, 0));
        } else {
            queryWrapper.eq(StoreDictionary::getParentId, parentId);
        }

        queryWrapper.orderByDesc(StoreDictionary::getSortId);
        queryWrapper.last("LIMIT 1");

        StoreDictionary maxDict = storeDictionaryMapper.selectOne(queryWrapper);
        return maxDict != null && maxDict.getSortId() != null ? maxDict.getSortId() : null;
    }

    /**
     * 调整排序：当记录的sortId改变时，调整同级其他记录的排序
     */
    private void adjustSortOrder(Integer currentId, Integer parentId, Integer oldSortId, Integer newSortId) {
        try {
            int oldOrder = oldSortId;
            int newOrder = newSortId;

            if (oldOrder == newOrder) {
                return;
            }

            LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
            queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
            queryWrapper.ne(StoreDictionary::getId, currentId);

            if (parentId == null || parentId == 0) {
                queryWrapper.and(wrapper -> wrapper.isNull(StoreDictionary::getParentId)
                        .or().eq(StoreDictionary::getParentId, 0));
            } else {
                queryWrapper.eq(StoreDictionary::getParentId, parentId);
            }

            List<StoreDictionary> siblings = storeDictionaryMapper.selectList(queryWrapper);

            if (siblings == null || siblings.isEmpty()) {
                return;
            }

            if (newOrder < oldOrder) {
                for (StoreDictionary sibling : siblings) {
                    try {
                        int siblingOrder = sibling.getSortId();
                        if (siblingOrder >= newOrder && siblingOrder < oldOrder) {
                            sibling.setSortId(siblingOrder + 1);
                            sibling.setUpdatedTime(new Date());
                            storeDictionaryMapper.updateById(sibling);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("无法解析sortId: {}", sibling.getSortId(), e);
                    }
                }
            } else if (newOrder > oldOrder) {
                for (StoreDictionary sibling : siblings) {
                    try {
                        int siblingOrder = sibling.getSortId();
                        if (siblingOrder > oldOrder && siblingOrder <= newOrder) {
                            sibling.setSortId(siblingOrder - 1);
                            sibling.setUpdatedTime(new Date());
                            storeDictionaryMapper.updateById(sibling);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("无法解析sortId: {}", sibling.getSortId(), e);
                    }
                }
            }
        } catch (NumberFormatException e) {
            log.error("调整排序失败，sortId格式错误: oldSortId={}, newSortId={}", oldSortId, newSortId, e);
        } catch (Exception e) {
            log.error("调整排序失败", e);
        }
    }

    /**
     * 处理从原节点移出时的排序调整
     */
    private void adjustSortOrderForMoveOut(Integer currentId, Integer oldParentId, Integer oldSortId) {
        try {
            int oldOrder = oldSortId;

            LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
            queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
            queryWrapper.ne(StoreDictionary::getId, currentId);

            if (oldParentId == null || oldParentId == 0) {
                queryWrapper.and(wrapper -> wrapper.isNull(StoreDictionary::getParentId)
                        .or().eq(StoreDictionary::getParentId, 0));
            } else {
                queryWrapper.eq(StoreDictionary::getParentId, oldParentId);
            }

            List<StoreDictionary> siblings = storeDictionaryMapper.selectList(queryWrapper);

            if (siblings == null || siblings.isEmpty()) {
                return;
            }

            for (StoreDictionary sibling : siblings) {
                try {
                    int siblingOrder = sibling.getSortId();
                    if (siblingOrder > oldOrder) {
                        sibling.setSortId(siblingOrder - 1);
                        sibling.setUpdatedTime(new Date());
                        storeDictionaryMapper.updateById(sibling);
                    }
                } catch (NumberFormatException e) {
                    log.warn("无法解析sortId: {}", sibling.getSortId(), e);
                }
            }
        } catch (NumberFormatException e) {
            log.error("移出节点排序调整失败，sortId格式错误: oldSortId={}", oldSortId, e);
        } catch (Exception e) {
            log.error("移出节点排序调整失败", e);
        }
    }

    /**
     * 处理移入新节点时的排序调整
     */
    private void adjustSortOrderForMoveIn(Integer currentId, Integer newParentId, Integer newSortId) {
        try {
            int newOrder = newSortId;

            LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
            queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
            queryWrapper.ne(StoreDictionary::getId, currentId);

            if (newParentId == null || newParentId == 0) {
                queryWrapper.and(wrapper -> wrapper.isNull(StoreDictionary::getParentId)
                        .or().eq(StoreDictionary::getParentId, 0));
            } else {
                queryWrapper.eq(StoreDictionary::getParentId, newParentId);
            }

            List<StoreDictionary> siblings = storeDictionaryMapper.selectList(queryWrapper);

            if (siblings == null || siblings.isEmpty()) {
                return;
            }

            for (StoreDictionary sibling : siblings) {
                try {
                    int siblingOrder = sibling.getSortId();
                    if (siblingOrder >= newOrder) {
                        sibling.setSortId(siblingOrder + 1);
                        sibling.setUpdatedTime(new Date());
                        storeDictionaryMapper.updateById(sibling);
                    }
                } catch (NumberFormatException e) {
                    log.warn("无法解析sortId: {}", sibling.getDictId(), e);
                }
            }
        } catch (NumberFormatException e) {
            log.error("移入节点排序调整失败，sortId格式错误: newSortId={}", newSortId, e);
        } catch (Exception e) {
            log.error("移入节点排序调整失败", e);
        }
    }

    /**
     * 批量导入意见反馈字典
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<String> importDictOpinionFeedback(MultipartFile file) {
        log.info("DictOpinionFeedbackServiceImpl.importDictOpinionFeedback fileName={}",
                file != null ? file.getOriginalFilename() : "null");
        try {
            if (file == null || file.isEmpty()) {
                return R.fail("文件不能为空");
            }

            String fileName = file.getOriginalFilename();
            if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
                return R.fail("文件格式不正确，请上传Excel文件");
            }

            List<String> errorMessages = new ArrayList<>();
            int successCount = 0;
            int totalCount = 0;

            try (InputStream inputStream = file.getInputStream();
                 Workbook workbook = new XSSFWorkbook(inputStream)) {
                Sheet sheet = workbook.getSheetAt(0);

                Row headerRow = sheet.getRow(5);
                if (headerRow == null) {
                    return R.fail("Excel文件格式不正确，缺少表头");
                }

                Map<String, Integer> headerMap = new HashMap<>();
                Field[] fields = DictionaryLibraryExcelVo.class.getDeclaredFields();
                for (int i = 0; i < headerRow.getLastCellNum(); i++) {
                    Cell cell = headerRow.getCell(i);
                    if (cell != null) {
                        String headerName = getCellValueAsString(cell);
                        if (StringUtils.isNotBlank(headerName)) {
                            headerMap.put(headerName.trim(), i);
                        }
                    }
                }

                for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                    Row row = sheet.getRow(rowIndex);
                    if (row == null) {
                        continue;
                    }

                    boolean isEmptyRow = true;
                    for (int i = 0; i < row.getLastCellNum(); i++) {
                        Cell cell = row.getCell(i);
                        if (cell != null && cell.getCellType() != CellType.BLANK) {
                            String cellValue = getCellValueAsString(cell);
                            if (StringUtils.isNotBlank(cellValue)) {
                                isEmptyRow = false;
                                break;
                            }
                        }
                    }
                    if (isEmptyRow) {
                        continue;
                    }

                    totalCount++;
                    DictionaryLibraryExcelVo excelVo = new DictionaryLibraryExcelVo();

                    for (Field field : fields) {
                        if (!field.isAnnotationPresent(ExcelHeader.class)) {
                            continue;
                        }
                        ExcelHeader excelHeader = field.getAnnotation(ExcelHeader.class);
                        String headerName = excelHeader.value();
                        Integer colIndex = headerMap.get(headerName);
                        if (colIndex == null) {
                            continue;
                        }

                        Cell cell = row.getCell(colIndex);
                        if (cell == null) {
                            continue;
                        }

                        field.setAccessible(true);
                        try {
                            String cellValue = getCellValueAsString(cell);
                            if (StringUtils.isNotBlank(cellValue)) {
                                field.set(excelVo, cellValue.trim());
                            }
                        } catch (Exception e) {
                            log.warn("读取字段{}失败：{}", headerName, e.getMessage());
                        }
                    }

                    try {
                        processImportData(excelVo, rowIndex + 1, errorMessages);
                        successCount++;
                    } catch (Exception e) {
                        errorMessages.add(String.format("第%d行：%s", rowIndex + 1, e.getMessage()));
                        log.error("导入第{}行数据失败", rowIndex + 1, e);
                    }
                }
            }

            StringBuilder message = new StringBuilder();
            message.append(String.format("导入完成：成功%d条，失败%d条", successCount, totalCount - successCount));
            if (!errorMessages.isEmpty()) {
                message.append("\n失败详情：\n");
                int maxErrors = Math.min(errorMessages.size(), 10);
                for (int i = 0; i < maxErrors; i++) {
                    message.append(errorMessages.get(i)).append("\n");
                }
                if (errorMessages.size() > 10) {
                    message.append(String.format("...还有%d条错误未显示", errorMessages.size() - 10));
                }
            }

            if (successCount == 0) {
                return R.fail(message.toString());
            } else {
                return R.success(message.toString());
            }
        } catch (Exception e) {
            log.error("导入意见反馈字典失败", e);
            return R.fail("导入失败：" + e.getMessage());
        }
    }

    /**
     * 处理导入数据
     */
    private void processImportData(DictionaryLibraryExcelVo excelVo, int rowIndex, List<String> errorMessages) {
        if (StringUtils.isBlank(excelVo.getFirstLevelName())) {
            throw new IllegalArgumentException("一级分类名称不能为空");
        }

        String firstLevelName = excelVo.getFirstLevelName().trim();
        String secondLevelName = StringUtils.isNotBlank(excelVo.getSecondLevelName())
                ? excelVo.getSecondLevelName().trim() : null;
        String thirdLevelName = StringUtils.isNotBlank(excelVo.getThirdLevelName())
                ? excelVo.getThirdLevelName().trim() : null;

        if (StringUtils.isNotBlank(thirdLevelName)) {
            createOrUpdateLevel(firstLevelName, secondLevelName, thirdLevelName, 3, excelVo.getHidden(), errorMessages, rowIndex);
        } else if (StringUtils.isNotBlank(secondLevelName)) {
            createOrUpdateLevel(firstLevelName, secondLevelName, null, 2, excelVo.getHidden(), errorMessages, rowIndex);
        } else {
            createOrUpdateLevel(firstLevelName, null, null, 1, excelVo.getHidden(), errorMessages, rowIndex);
        }
    }

    /**
     * 创建或更新分类级别
     */
    private void createOrUpdateLevel(String firstLevelName, String secondLevelName, String thirdLevelName,
                                     int level, String hidden, List<String> errorMessages, int rowIndex) {
        try {
            StoreDictionary firstLevel = findOrCreateLevel(firstLevelName, null, 0, hidden);
            if (firstLevel == null) {
                throw new IllegalArgumentException("创建一级分类失败");
            }
            if (level >= 2 && StringUtils.isNotBlank(secondLevelName)) {
                StoreDictionary secondLevel = findOrCreateLevel(secondLevelName, firstLevel.getId(), 1, hidden);
                if (secondLevel == null) {
                    throw new IllegalArgumentException("创建二级分类失败");
                }

                if (level >= 3 && StringUtils.isNotBlank(thirdLevelName)) {
                    StoreDictionary thirdLevel = findOrCreateLevel(thirdLevelName, secondLevel.getId(), 2, hidden);
                    if (thirdLevel == null) {
                        throw new IllegalArgumentException("创建三级分类失败");
                    }
                }
            }
        } catch (Exception e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * 查找或创建分类
     */
    private StoreDictionary findOrCreateLevel(String dictDetail, Integer parentId, int expectedLevel, String hidden) {
        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(StoreDictionary::getTypeName, "opinion_feedback", "opinion_feedback_type", "opinion_feedback_classify");
        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
        queryWrapper.eq(StoreDictionary::getDictDetail, dictDetail);

        if (parentId == null || parentId == 0) {
            queryWrapper.and(wrapper -> wrapper.isNull(StoreDictionary::getParentId)
                    .or().eq(StoreDictionary::getParentId, 0));
        } else {
            queryWrapper.eq(StoreDictionary::getParentId, parentId);
        }

        StoreDictionary existing = storeDictionaryMapper.selectOne(queryWrapper);

        if (existing != null) {
            return existing;
        }

        StoreDictionary newDict = new StoreDictionary();
        newDict.setDictDetail(dictDetail);
        // 一级为筛选条件，二级为筛选条件种类，三级为分类，四级为时间范围
        if (expectedLevel == 0) {
            newDict.setTypeDetail("意见反馈");
            newDict.setTypeName("opinion_feedback");
        } else if (expectedLevel == 1) {
            newDict.setTypeDetail("意见反馈种类");
            newDict.setTypeName("opinion_feedback_type");
        } else if (expectedLevel == 2) {
            newDict.setTypeDetail("意见反馈分类");
            newDict.setTypeName("opinion_feedback_classify");
        }
        newDict.setParentId(parentId == null ? null : parentId);
        newDict.setHidden(StringUtils.isNotBlank(hidden) && hidden.equals("隐藏") ? 1 : 0);
        newDict.setDeleteFlag(0);
        newDict.setCreatedTime(new Date());

        String maxDictId = getMaxDictIdByTypeName(newDict.getTypeName());
        newDict.setDictId(String.valueOf(maxDictId == null ? 1 : Integer.parseInt(maxDictId) + 1));

        Integer maxSortId = getMaxSortIdByParentId(newDict.getParentId());
        newDict.setSortId(maxSortId == null ? 1 : maxSortId + 1);

        boolean saved = this.save(newDict);
        return saved ? newDict : null;
    }

    private String buildTypeDetail(int expectedLevel) {
        if (expectedLevel == 0) {
            return "意见反馈一级";
        } else if (expectedLevel == 1) {
            return "意见反馈二级";
        } else if (expectedLevel == 2) {
            return "意见反馈三级";
        }
        return "意见反馈";
    }

    /**
     * 获取单元格值（字符串格式）
     */
    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return null;
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    double numericValue = cell.getNumericCellValue();
                    if (numericValue == (long) numericValue) {
                        return String.valueOf((long) numericValue);
                    } else {
                        return String.valueOf(numericValue);
                    }
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return null;
        }
    }

    /**
     * 下载意见反馈字典导入模板
     */
    @Override
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        log.info("DictOpinionFeedbackServiceImpl.downloadTemplate");

        XSSFWorkbook workbook = new XSSFWorkbook();
        try {
            Sheet sheet = workbook.createSheet("意见反馈字典导入模板");

            Field[] fields = DictionaryLibraryExcelVo.class.getDeclaredFields();
            List<Field> excelFields = new ArrayList<>();
            for (Field field : fields) {
                if (field.isAnnotationPresent(ExcelHeader.class)) {
                    excelFields.add(field);
                }
            }

            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setFontHeightInPoints((short) 12);
            CellStyle headerCellStyle = workbook.createCellStyle();
            headerCellStyle.setFont(headerFont);
            headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
            headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            headerCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            headerCellStyle.setBorderBottom(BorderStyle.THIN);
            headerCellStyle.setBorderTop(BorderStyle.THIN);
            headerCellStyle.setBorderLeft(BorderStyle.THIN);
            headerCellStyle.setBorderRight(BorderStyle.THIN);

            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < excelFields.size(); i++) {
                Field field = excelFields.get(i);
                ExcelHeader excelHeader = field.getAnnotation(ExcelHeader.class);
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(excelHeader.value());
                cell.setCellStyle(headerCellStyle);
            }

            sheet.setColumnWidth(0, 25 * 256);
            sheet.setColumnWidth(1, 25 * 256);
            sheet.setColumnWidth(2, 25 * 256);
            sheet.setColumnWidth(3, 15 * 256);

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("意见反馈字典导入模板", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            OutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    log.error("关闭workbook失败", e);
                }
            }
        }
    }
}


