package com.yfd.platform.modules.experimentalData.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.yfd.platform.modules.experimentalData.domain.TsNodes;
import com.yfd.platform.modules.experimentalData.mapper.TsFilesMapper;
import com.yfd.platform.modules.experimentalData.mapper.TsNodesMapper;
import com.yfd.platform.modules.experimentalData.service.ITsFilesService;
import com.yfd.platform.modules.experimentalData.service.ITsNodesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.yfd.platform.modules.specialDocument.mapper.NodesMapper;
import com.yfd.platform.modules.storage.context.StorageSourceContext;
import com.yfd.platform.modules.storage.mapper.StorageSourceMapper;
import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
import com.yfd.platform.modules.storage.model.request.NewFolderRequest;
import com.yfd.platform.modules.storage.model.request.RenameFolderRequest;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 试验任务节点表 服务实现类
 * </p>
 *
 * @author LiMengNan
 * @since 2025-01-21
 */
@Service
public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> implements ITsNodesService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);

    //试验任务节点表 Mapper
    @Resource
    private TsNodesMapper tsNodesMapper;

    //试验任务文档表 Mapper
    @Resource
    private TsFilesMapper tsFilesMapper;

    //实验任务文档表
    @Resource
    private ITsFilesService tsFilesService;

    @Resource
    private StorageSourceContext storageSourceContext;

    @Override
    public List<Map<String, Object>> getTsNodesTree(String nodeName, String taskId) {
        // 查询所有节点数据
        List<Map<String, Object>> allNodes = getAllNodes(taskId);

        // 查找所有根节点（parentId为"00"的节点）
        List<Map<String, Object>> rootNodes = findRootNodes(allNodes, taskId);

        // 如果未找到根节点，返回空列表
        if (rootNodes.isEmpty()) {
            return new ArrayList<>();
        }

        // 存储最终结果
        List<Map<String, Object>> result = new ArrayList<>();

        // 如果 nodeName 为空，返回所有根节点的完整树形结构
        if (StringUtils.isEmpty(nodeName)) {
            for (Map<String, Object> rootNode : rootNodes) {
                result.addAll(buildFullTree(rootNode, allNodes));
            }
            return result;
        }

        // 否则，返回从根节点到目标节点的树形结构
        for (Map<String, Object> rootNode : rootNodes) {
            List<Map<String, Object>> tree = buildTreeToTargetNode(rootNode, allNodes, nodeName);
            if (!tree.isEmpty()) {
                result.addAll(tree);
            }
        }

        // 返回结果
        return result;
    }

    /**
     * 查询所有节点数据
     *
     * @param taskId 任务ID（用于精确查询）
     * @return 返回所有节点列表
     */
    private List<Map<String, Object>> getAllNodes(String taskId) {
        // 创建查询条件
        QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(
                "node_id as nodeId",              // 节点ID
                "node_name as nodeName",         // 节点名称
                "task_id as taskId",             // 所属任务ID
                "parent_id as parentId",         // 父节点ID
                "node_order as nodeOrder",       // 节点顺序
                "create_time as createTime",     // 创建时间
                "creator"                        // 创建人
        );

        // 如果任务ID不为空，添加精确查询条件
        if (StringUtils.isNotEmpty(taskId)) {
            queryWrapper.eq("task_id", taskId);
        }
        // 按节点顺序升序排序
        queryWrapper.orderByAsc("node_order");

        // 查询所有符合条件的节点
        return tsNodesMapper.selectMaps(queryWrapper);
    }

    /**
     * 查找所有根节点（parentId为"00"的节点）
     *
     * @param allNodes 所有节点数据
     * @param taskId   任务ID
     * @return 返回所有根节点列表
     */
    private List<Map<String, Object>> findRootNodes(List<Map<String, Object>> allNodes, String taskId) {
        List<Map<String, Object>> rootNodes = new ArrayList<>();
        for (Map<String, Object> node : allNodes) {
            if ("00".equals(node.get("parentId").toString()) && taskId.equals(node.get("taskId").toString())) {
                rootNodes.add(node);
            }
        }
        return rootNodes;
    }

    /**
     * 构建完整的树形结构
     *
     * @param currentNode 当前节点
     * @param allNodes    所有节点数据
     * @return 返回当前节点的子树
     */
    private List<Map<String, Object>> buildFullTree(Map<String, Object> currentNode, List<Map<String, Object>> allNodes) {
        // 查找当前节点的所有子节点
        List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("nodeId").toString());

        // 递归构建子树
        List<Map<String, Object>> tree = new ArrayList<>();
        for (Map<String, Object> child : children) {
            List<Map<String, Object>> childTree = buildFullTree(child, allNodes);
            if (!childTree.isEmpty()) {
                tree.addAll(childTree);
            }
        }

        // 将当前节点加入树中
        Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
        if (!tree.isEmpty()) {
            nodeWithChildren.put("children", tree);
        }

        return Collections.singletonList(nodeWithChildren);
    }

    /**
     * 查找当前节点的所有子节点
     *
     * @param allNodes 所有节点数据
     * @param parentId 父节点ID
     * @return 返回所有子节点列表
     */
    private List<Map<String, Object>> findChildren(List<Map<String, Object>> allNodes, String parentId) {
        List<Map<String, Object>> children = new ArrayList<>();
        for (Map<String, Object> node : allNodes) {
            if (parentId.equals(node.get("parentId").toString())) {
                children.add(node);
            }
        }
        return children;
    }

    /**
     * 构建从根节点到目标节点的树形结构
     *
     * @param currentNode 当前节点
     * @param allNodes    所有节点数据
     * @param nodeName    目标节点名称
     * @return 返回从根节点到目标节点的树形结构
     */
    private List<Map<String, Object>> buildTreeToTargetNode(Map<String, Object> currentNode, List<Map<String, Object>> allNodes, String nodeName) {


        List<Map<String, Object>> result = new ArrayList<>();

        // 查找当前节点的所有子节点
        List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("nodeId").toString());

        // 递归查找目标节点
        for (Map<String, Object> child : children) {
            List<Map<String, Object>> childTree = buildTreeToTargetNode(child, allNodes, nodeName);
            if (!childTree.isEmpty()) {
                // 如果找到目标节点，将当前节点加入树中，并将其作为子节点
                Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
                nodeWithChildren.put("children", childTree);
                result.add(nodeWithChildren);  // 将当前节点加入结果列表
            }
        }
        // 如果当前节点符合条件且没有被添加到result，则将其添加
        if (currentNode.get("nodeName") instanceof String && ((String) currentNode.get("nodeName")).contains(nodeName) && result.isEmpty()) {
            result.add(currentNode);  // 将当前节点添加到结果列表
        }

        // 返回包含所有符合条件的树结构的列表
        return result;
    }


    /**********************************
     * 用途说明: 增加试验任务节点
     * 参数说明  nodes 专项文档节点信息
     * 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败
     ***********************************/
    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务注解，遇到异常时回滚
    public ResponseResult addTsNodes(TsNodes tsnodes) {


        // 校验文件名是否包含非法字符
        String nodeName = tsnodes.getNodeName();
        if (containsInvalidCharacters(nodeName)) {
            return ResponseResult.error("文件名包含非法字符（<>:\"/\\|?*）！");
        }
        //  差不多的流程  就是提出来  然后判断  如果两个 中有一个是true
        //获取当前登录用户
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginuser = (LoginUser) authentication.getPrincipal();
        //创建人是当前登录人
        tsnodes.setCreator(loginuser.getUsername());

        //当前操作时间
        LocalDateTime now = LocalDateTime.now();
        // 转换为 Timestamp
        Timestamp currentTime = Timestamp.valueOf(now);
        tsnodes.setCreateTime(currentTime);

        //通过获取上级节点的条数 设置节点顺序
        QueryWrapper<TsNodes> queryWrapperNodeOrder = new QueryWrapper<>();
        int orderno = this.count(queryWrapperNodeOrder.eq("parent_id", tsnodes.getParentId())) + 1;
        //判断节点名称是否存在
        QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("node_name", tsnodes.getNodeName());//名称
        queryWrapper.eq("task_id", tsnodes.getTaskId());//所属任务ID
        queryWrapper.eq("parent_id", tsnodes.getParentId());//所属任务ID
        int count = tsNodesMapper.selectCount(queryWrapper);
        // 大于0说明 区域名称重复
        if (count > 0) {
            return ResponseResult.error("节点名称已存在！");
        }
        //序号
        tsnodes.setNodeOrder(orderno);



        int valueAdded = tsNodesMapper.insert(tsnodes);
        if (valueAdded == 1) {
            LOGGER.info("tsnodes表结构增加成功");
            //判断文件夹是否创建
            AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("local");
            boolean flag = fileService.isFolderCreated(File.separator + tsnodes.getNodeId());
            //如果是false 说明没有创建  那就新建一个文件夹
            if(!flag){
                //本地创建文件夹
                AbstractBaseFileService<?> fileServiceData = storageSourceContext.getByStorageKey("local");
                boolean flagData = fileServiceData.newFolder(File.separator, tsnodes.getNodeId());
                if(!flagData){
                    LOGGER.error("创建节点文件夹失败！");
                    return ResponseResult.error("新增节点失败!");
                }
            }
            return ResponseResult.success();
        } else {
            LOGGER.error("tsnodes表结构增加失败");
            return ResponseResult.error();
        }

    }


    // 校验文件名是否包含非法字符
    private boolean containsInvalidCharacters(String nodeName) {
        // 定义非法字符的正则表达式
        String regex = "[<>:\"/\\\\|?*]";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(nodeName);
        return matcher.find();
    }


    /**********************************
     * 用途说明: 修改试验任务节点
     * 参数说明  tsnodes  试验任务节点信息
     * 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
     ***********************************/
    @Override
    public ResponseResult updateTsNodes(TsNodes tsnodes) {

        // 校验文件名是否包含非法字符
        String nodeName = tsnodes.getNodeName();
        if (containsInvalidCharacters(nodeName)) {
            return ResponseResult.error("文件名包含非法字符（<>:\"/\\|?*）！");
        }

        //查询没改之前的节点名称
        TsNodes nodesold = tsNodesMapper.selectById(tsnodes.getNodeId());

        //老的节点名称
        String nodeNameOld = null;
        if (ObjUtil.isNotEmpty(nodesold)) {
            nodeNameOld = nodesold.getNodeName();
        }

        //获取当前登录用户
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginuser = (LoginUser) authentication.getPrincipal();
        //创建人是当前登录人
        tsnodes.setCreator(loginuser.getUsername());

        //判断节点名称是否存在
        QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("node_name", tsnodes.getNodeName());//名称
        queryWrapper.eq("parent_id", tsnodes.getParentId());//父节点
        int count = tsNodesMapper.selectCount(queryWrapper);
        // 大于0说明 区域名称重复
        if (count > 0) {
            return ResponseResult.error("节点名称已存在！");
        }
        int valueAdded = tsNodesMapper.updateById(tsnodes);
        if (valueAdded == 1) {
            LOGGER.info("tsnodes表结构修改成功");
            return ResponseResult.success();
        } else {
            LOGGER.error("tsnodes表结构修改失败");
            return ResponseResult.error();
        }
    }

    /**********************************
     * 用途说明: 根据ID删除试验任务节点
     * 参数说明  id 试验任务节点ID
     * 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
     ***********************************/
    @Override
    public boolean deleteTsNodesById(String id) {
        //根据ID 查询当前数据
        TsNodes tsNodes = tsNodesMapper.selectById(id);
        //删除之前  先拼路径  然后删除本地和minio的文件夹 最后删除表结构
        //删除当前节点的 文件
        QueryWrapper<TsFiles> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("node_id", tsNodes.getNodeId());
        queryWrapper1.eq("task_id", tsNodes.getTaskId());
        List<TsFiles> tsFiles = tsFilesMapper.selectList(queryWrapper1);

        List<String> dataset = new ArrayList<>();
        if (tsFiles != null && !tsFiles.isEmpty()) {
            dataset = tsFiles.stream()
                    .map(TsFiles::getId)  // 假设 TsFiles 类中有 getId() 方法
                    .collect(Collectors.toList());
        }
        //批量删除TsFiles表数据
        if (dataset.size() > 0) {
            tsFilesService.deleteTsFilesByIds(dataset, "local");
        }

        // 递归删除子节点
        deleteChildren(tsNodes.getNodeId(), tsNodes.getTaskId());
        // 删除当前节点
        int deleteCount = tsNodesMapper.deleteById(id);
        if (deleteCount == 1) {
            LOGGER.info("tsnodes表结删除改成功");
            return true;
        } else {
            LOGGER.error("tsnodes表结构删除失败");
            return false;
        }
    }

    /**
     * 递归删除子节点
     *
     * @param parentId 父节点ID
     */
    private void deleteChildren(String parentId, String taskId) {
        // 使用 QueryWrapper 查询当前节点的所有子节点
        QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentId); // parent_id = #{parentId}
        queryWrapper.eq("task_id", taskId); // parent_id = #{parentId}
        List<TsNodes> children = tsNodesMapper.selectList(queryWrapper);

        // 递归删除每个子节点
        for (TsNodes child : children) {
            deleteChildren(child.getNodeId(), child.getTaskId()); // 递归删除子节点的子节点
            tsNodesMapper.deleteById(child.getNodeId()); // 删除当前子节点
            //批量文件的数据
            QueryWrapper<TsFiles> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("node_id", child.getNodeId());
            queryWrapper1.eq("task_id", taskId);
            List<TsFiles> tsFiles = tsFilesMapper.selectList(queryWrapper1);

            List<String> dataset = new ArrayList<>();
            if (tsFiles != null && !tsFiles.isEmpty()) {
                dataset = tsFiles.stream()
                        .map(TsFiles::getId)  // 假设 TsFiles 类中有 getId() 方法
                        .collect(Collectors.toList());
            }
            //批量删除TsFiles表数据
            if (dataset.size() > 0) {
                tsFilesService.deleteTsFilesByIds(dataset, "local");
            }
        }
    }


    /**********************************
     * 用途说明: 根据任务ID删除下面所有的节点以及节点下面所有的文件
     * 参数说明  taskId 试验任务ID
     * 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
     ***********************************/
    @Override
    public boolean deleteTsNodesByTaskId(String taskId) {
        Boolean value = false;
        //根据任务ID 查询所有的集合  不管层级结构全部都删除
        QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_id",taskId);
        List<TsNodes> tsNodesList = tsNodesMapper.selectList(queryWrapper);
        if(tsNodesList == null && tsNodesList.isEmpty()){
          return true;
        }

        for(TsNodes tsNodes : tsNodesList){
         //删除文件表
         Boolean deleteTsFiles =   tsFilesService.deleteTsFilesByNodeId(tsNodes.getNodeId(),tsNodes.getTaskId());
         //如果删除成功 接着删除节点表数据
         if(deleteTsFiles){
             // 删除当前节点
             int deleteCount = tsNodesMapper.deleteById(tsNodes.getNodeId());
             if (deleteCount == 1) {
                 LOGGER.info("tsnodes表结删除改成功");
                 value = true;
             } else {
                 LOGGER.error("tsnodes表结构删除失败");
                 value = false;
             }
         }
        }
        return value;
    }

}
