package com.dcs.dcs.service.impl;

import com.dcs.common.exception.CustomException;
import com.dcs.dcs.domain.DcsEquipment;
import com.dcs.dcs.domain.vo.DcsEquipmentFormVo;
import com.dcs.dcs.mapper.DcsEquipmentMapper;
import com.dcs.dcs.service.IDcsEquipmentService;
import com.dcs.equipment.task.ModbusTcpTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.dcs.equipment.constants.ModbusConstants.*;

/**
 * 设备管理Service业务层处理
 * 
 * @author hmy
 * @date 2025-03-08
 */
@Service
public class DcsEquipmentServiceImpl implements IDcsEquipmentService 
{
    @Autowired
    private DcsEquipmentMapper dcsEquipmentMapper;
    @Resource
    private DcsFlowServiceImpl dcsFlowService;



    @Override
    public List<DcsEquipmentFormVo> buildTree(List<DcsEquipmentFormVo> equipmentList) {
        // 1. 先构建一个 Map，保证所有节点都在 Map 中
        Map<Long, DcsEquipmentFormVo> equipmentMap = new HashMap<>();
        for (DcsEquipmentFormVo equipment : equipmentList) {
            equipmentMap.put(equipment.getEquipmentId(), equipment);
        }

        // 2. 进行父子关联
        List<DcsEquipmentFormVo> rootNodes = new ArrayList<>();
        for (DcsEquipmentFormVo equipment : equipmentList) {
            if (equipment.getParentsId() == null || equipment.getParentsId().equals(0L)) {
                rootNodes.add(equipment);
            } else {
                DcsEquipmentFormVo parent = equipmentMap.get(equipment.getParentsId());
                if (parent != null) {
                    List<DcsEquipmentFormVo> children = parent.getChildren();
                    children.add(equipment);
                    parent.setChildren(children);
                }
            }
        }

        return rootNodes;
    }

    /**
     * 获取设备id对应索引值列表，用于初始化
     * @return
     */
    @Override
    public Map<Integer, Integer> getEquipmentIndexList() {
        Map<Integer, Integer> swappedMap = new HashMap<>();
        List<DcsEquipmentFormVo> equipmentFormVoList = ModbusTcpTask.equipmentFormVoList;
        for (int i = 0; i < equipmentFormVoList.size(); i++) {
            swappedMap.put(Math.toIntExact(equipmentFormVoList.get(i).getEquipmentId()), i);
        }
        return swappedMap;
    }

    /**
     * 获取树状设备名
     * @param dataType
     * @return
     */
    @Override
    public List<Map<String, Object>> getEquipmentNameList(String dataType) {
        List<String> dataTypes = new ArrayList<>();
        switch (dataType) {
            case "bool"://布尔型
                dataTypes.add(COIL_DATA_TYPE);
                break;
            case "data"://浮点型和整型
                dataTypes= Arrays.asList(INT_DATA_TYPE,FLOAT_DATA_TYPE);
                break;
            default:
                throw new CustomException("该数据类型暂无处理");
        }
        List<DcsEquipment> dcsEquipments = dcsEquipmentMapper.selectDcsEquipmentListByDataTypes(dataTypes);
        List<DcsEquipment> allEquipments = dcsEquipmentMapper.selectDcsEquipmentList(new DcsEquipment());
        return buildEquipmentTree(dcsEquipments, allEquipments);
    }

    @Override
    public List<Map<String, Object>> getEquipmentSensorTree() {
        DcsEquipment equipment= new DcsEquipment();
        equipment.setEquipmentName("数据");//传感器相关寄存器（温度数据、压力数据、称重数据）
        List<DcsEquipment> dcsEquipments = dcsEquipmentMapper.selectDcsEquipmentList(equipment);
        List<DcsEquipment> allEquipments = dcsEquipmentMapper.selectDcsEquipmentList(new DcsEquipment());
        List<Map<String,Object>> tree=buildEquipmentTree(dcsEquipments, allEquipments);
        return filterTree(tree);
    }

    //剔除多余的设备信息
    public static List<Map<String, Object>> filterTree(List<Map<String, Object>> tree) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> node : tree) {
            Map<String, Object> filtered = filterNode(node);
            if (filtered != null) {
                result.add(filtered);
            }
        }
        return result;
    }

    private static Map<String, Object> filterNode(Map<String, Object> node) {
        String label = (String) node.get("label");

        // 检查是否有 children
        List<Map<String, Object>> children = (List<Map<String, Object>>) node.get("children");
        List<Map<String, Object>> filteredChildren = new ArrayList<>();

        if (children != null) {
            for (Map<String, Object> child : children) {
                Map<String, Object> filteredChild = filterNode(child);
                if (filteredChild != null) {
                    filteredChildren.add(filteredChild);
                }
            }
        }

        // 如果当前节点 label 包含“数据”，或有包含“数据”的子节点，就保留
        if ((label != null && label.contains("数据")) || !filteredChildren.isEmpty()) {
            Map<String, Object> newNode = new LinkedHashMap<>();
            newNode.put("label", label);
            newNode.put("value", node.get("value"));
            if (!filteredChildren.isEmpty()) {
                newNode.put("children", filteredChildren);
            }
            return newNode;
        }

        return null;
    }


    public List<Map<String, Object>> buildEquipmentTree(List<DcsEquipment> dcsEquipments, List<DcsEquipment> allEquipments) {
        // 1. 先构建 id -> 设备映射
        Map<Long, DcsEquipment> equipmentMap = allEquipments.stream()
                .collect(Collectors.toMap(DcsEquipment::getEquipmentId, e -> e));

        // 2. 构建 id -> 子设备列表映射
        Map<Long, List<DcsEquipment>> childrenMap = new HashMap<>();
        for (DcsEquipment equipment : allEquipments) {
            childrenMap.computeIfAbsent(equipment.getParentsId(), k -> new ArrayList<>()).add(equipment);
        }

        // 3. 追溯所有最底层设备的父级链
        Set<Long> topLevelIds = new HashSet<>();
        for (DcsEquipment equipment : dcsEquipments) {
            findTopParent(equipment, equipmentMap, topLevelIds);
        }

        // 4. 生成完整的树结构
        List<Map<String, Object>> tree = new ArrayList<>();
        for (Long topId : topLevelIds) {
            DcsEquipment root = equipmentMap.get(topId);
            if (root != null) {
                tree.add(buildTreeNode(root, childrenMap));
            }
        }
        return tree;
    }

    // 递归找到最顶层父级设备
    private void findTopParent(DcsEquipment equipment, Map<Long, DcsEquipment> equipmentMap, Set<Long> topLevelIds) {
        if (equipment == null) return;
        if (equipment.getParentsId() == null || equipment.getParentsId() == 0) {
            topLevelIds.add(equipment.getEquipmentId()); // 设备无父级，说明是根节点
        } else {
            findTopParent(equipmentMap.get(equipment.getParentsId()), equipmentMap, topLevelIds);
        }
    }

    // 递归构建树形结构
    private Map<String, Object> buildTreeNode(DcsEquipment equipment, Map<Long, List<DcsEquipment>> childrenMap) {
        Map<String, Object> node = new HashMap<>();
        node.put("value", equipment.getEquipmentCode());
        node.put("label", equipment.getEquipmentName());
        List<DcsEquipment> children = childrenMap.get(equipment.getEquipmentId());
        if (children != null && !children.isEmpty()) {
            List<Map<String, Object>> childNodes = new ArrayList<>();
            for (DcsEquipment child : children) {
                childNodes.add(buildTreeNode(child, childrenMap));
            }
            node.put("children", childNodes);
        }
        return node;
    }



    /**
     * 查询设备管理
     * 
     * @param equipmentId 设备管理主键
     * @return 设备管理
     */
    @Override
    public DcsEquipment selectDcsEquipmentByEquipmentId(Long equipmentId)
    {
        return dcsEquipmentMapper.selectDcsEquipmentByEquipmentId(equipmentId);
    }



    /**
     * 查询设备管理列表
     * 
     * @param dcsEquipment 设备管理
     * @return 设备管理
     */
    @Override
    public List<DcsEquipment> selectDcsEquipmentList(DcsEquipment dcsEquipment) {
        return dcsEquipmentMapper.selectDcsEquipmentList(dcsEquipment);
    }

    @Override
    public List<DcsEquipmentFormVo> selectDcsEquipmentVoList(DcsEquipment dcsEquipment)
    {
        List<DcsEquipmentFormVo> list = dcsEquipmentMapper.selectDcsEquipmentVoList(dcsEquipment);
        //处理flowName数据
        for (DcsEquipmentFormVo equipmentFormVo : list) {
            String flowIdStr = equipmentFormVo.getFlowId(); // "1,2"
            if (flowIdStr != null && !flowIdStr.isEmpty()) {
                String[] flowIds = flowIdStr.split(","); // ["1", "2"]
                List<String> flowNames = new ArrayList<>();
                for (String flowId : flowIds) {
                    //通过flowId获取flowName
                    flowNames.add(dcsFlowService.selectFlowNameByFlowId(Long.valueOf(flowId)));
                }
                // 设置 flowNames
                equipmentFormVo.setFlowName(String.join(",", flowNames));
            }
        }
        return list;
    }

    /**
     * 新增设备管理
     * 
     * @param dcsEquipment 设备管理
     * @return 结果
     */
    @Override
    public int insertDcsEquipment(DcsEquipment dcsEquipment)
    {
        DcsEquipment d= dcsEquipmentMapper.selectOneByEquipmentCode(dcsEquipment.getEquipmentCode());
        if(d!=null){
            throw new CustomException("设备标识已存在");
        }
        return dcsEquipmentMapper.insertDcsEquipment(dcsEquipment);
    }

    /**
     * 修改设备管理
     * 
     * @param dcsEquipment 设备管理
     * @return 结果
     */
    @Override
    public int updateDcsEquipment(DcsEquipment dcsEquipment)
    {
        DcsEquipment d=dcsEquipmentMapper.selectOneByEquipmentCode(dcsEquipment.getEquipmentCode());
        if(d!=null&&!d.getEquipmentId().equals(dcsEquipment.getEquipmentId())){
            throw new CustomException("设备标识已存在");
        }
        return dcsEquipmentMapper.updateDcsEquipment(dcsEquipment);
    }

    /**
     * 批量删除设备管理
     * 
     * @param equipmentIds 需要删除的设备管理主键
     * @return 结果
     */
    @Override
    public int deleteDcsEquipmentByEquipmentIds(Long[] equipmentIds)
    {
        return dcsEquipmentMapper.deleteDcsEquipmentByEquipmentIds(equipmentIds);
    }

    /**
     * 删除设备管理信息
     * 
     * @param equipmentId 设备管理主键
     * @return 结果
     */
    @Override
    public int deleteDcsEquipmentByEquipmentId(Long equipmentId)
    {
        return dcsEquipmentMapper.deleteDcsEquipmentByEquipmentId(equipmentId);
    }
}
