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

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.algorithm.domain.*;
import com.yfd.platform.modules.algorithm.mapper.AlgorithmClassComponentMapper;
import com.yfd.platform.modules.algorithm.mapper.AlgorithmClassMapper;
import com.yfd.platform.modules.algorithm.service.IAlgorithmClassService;
import com.yfd.platform.modules.algorithm.service.IAlgorithmDeviceService;
import com.yfd.platform.modules.algorithm.service.IAlgorithmParamsService;
import com.yfd.platform.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhengsl
 * @since 2025-05-13
 */
@Service
@Transactional
public class AlgorithmClassServiceImpl extends ServiceImpl<AlgorithmClassMapper, AlgorithmClass> implements IAlgorithmClassService {

    @Resource
    private IAlgorithmParamsService algorithmParamsService;
    @Resource
    private IAlgorithmDeviceService algorithmDeviceService;
    @Resource
    private AlgorithmClassComponentMapper algorithmClassComponentMapper;

    /**********************************
     * 用途说明: 新增算法分类
     * 参数说明 algorithmClass
     * 返回值说明: boolean是否成功
     ***********************************/
    @Override
    public boolean addAlgorithmClass(AlgorithmClass algorithmClass) {
        return this.saveOrUpdate(algorithmClass);
    }

    /**********************************
     * 用途说明: 修改算法分类
     * 参数说明 algorithmClass 算法分类对象
     * 返回值说明: boolean 是否成功
     ***********************************/
    @Override
    public boolean updateAlgorithmClass(AlgorithmClass algorithmClass) {
        return this.saveOrUpdate(algorithmClass);
    }

    /**********************************
     * 用途说明: 删除算法分类
     * 参数说明 id 算法分类Id
     * 返回值说明: boolean 是否成功
     ***********************************/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAlgorithmClass(String id) {
        LambdaQueryWrapper<AlgorithmParams> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlgorithmParams::getAlgorithmId, id);
        boolean removeDevice =
                algorithmDeviceService.remove(new LambdaQueryWrapper<AlgorithmDevice>().eq(AlgorithmDevice::getAlgorithmId, id));
        algorithmClassComponentMapper.delete(new LambdaQueryWrapper<AlgorithmClassComponent>().eq(AlgorithmClassComponent::getAlgorithmId, id));
        boolean removeParams = algorithmParamsService.remove(queryWrapper);
        boolean b = this.removeById(id);
        if (removeDevice && b && removeParams) {
            return true;
        }
        throw new RuntimeException("删除错误");
    }

    /**********************************
     * 用途说明: 保存算法分类和算法参数
     * 参数说明 algorithmParamsRequest
     * 返回值说明: boolean
     ***********************************/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addAlgorithmClassAndParams(AlgorithmParamsRequest algorithmParamsRequest) {
        AlgorithmClass algorithmClass = algorithmParamsRequest.getAlgorithmClass();
        if (ObjUtil.isEmpty(algorithmClass)) {
            return false;
        }
        if (StrUtil.isBlank(algorithmClass.getId())) {
            String uuid = IdUtil.fastSimpleUUID();
            algorithmClass.setId(uuid);
        }
        String currentUsername = SecurityUtils.getCurrentUsername();
        this.saveOrUpdate(algorithmClass);
        List<AlgorithmParams> algorithmParamsList = algorithmParamsRequest.getAlgorithmParamsList();
        // 获取修改的参数id
        Set<String> paramIdList =
                algorithmParamsList.stream().filter(a -> StrUtil.isNotBlank(a.getId())).map(AlgorithmParams::getId).collect(Collectors.toSet());

        // 排除修改的算法参数，删除掉其他算法参数和点位信息

        LambdaQueryWrapper<AlgorithmDevice> deviceQueryWrapper = new LambdaQueryWrapper<>();
        deviceQueryWrapper.eq(AlgorithmDevice::getAlgorithmId, algorithmClass.getId());
        if (paramIdList.size() > 0) {
            deviceQueryWrapper.notIn(AlgorithmDevice::getParamId, paramIdList);
        }
        algorithmDeviceService.remove(deviceQueryWrapper);

        LambdaQueryWrapper<AlgorithmParams> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlgorithmParams::getAlgorithmId, algorithmClass.getId());
        if (paramIdList.size() > 0) {
            queryWrapper.notIn(AlgorithmParams::getId, paramIdList);
        }
        algorithmParamsService.remove(queryWrapper);

        algorithmParamsList.forEach(r -> {
            r.setAlgorithmId(algorithmClass.getId());
            r.setLastmodifier(currentUsername);
            r.setLastmodifydate(LocalDateTime.now());
        });
        if (algorithmParamsList.size() > 0) {
            return algorithmParamsService.saveOrUpdateBatch(algorithmParamsList);
        }
        return true;
    }

    /***********************************
     * 用途说明: 获取算法分类树
     * 参数说明 algorithmClassName
     * 返回值说明: java.util.List<com.yfd.platform.modules.basedata.domain.TreeNode>
     ***********************************/
    @Override
    public List<TreeNode> getAlgorithmComponentTree(String stationCode,String algorithmClassName) {
        List<Map<String, Object>> dataList =
                algorithmClassComponentMapper.getAlgorithmComponentList(stationCode,algorithmClassName);
        List<TreeNode> treeNodes = this.buildSignalTree(dataList);
        if (treeNodes.size() <= 0) {
            return treeNodes;
        }
        return treeNodes.get(0).getChildren();
    }

    /**********************************
     * 用途说明: 构造树
     * 参数说明 dataList 数据
     * 返回值说明: java.util.List<com.yfd.platform.modules.basedata.domain.TreeNode>
     ***********************************/
    public List<TreeNode> buildSignalTree(List<Map<String, Object>> dataList) {
        Map<String, TreeNode> nodeMap = new HashMap<>();
        List<TreeNode> roots = new ArrayList<>();

        for (Map<String, Object> data : dataList) {
            // 解析字段（根据实际字段名称调整）
            String stationCode = (String) data.get("stationCode");
            String stationName = (String) data.get("stationName");
            String algorithmId = (String) data.get("algorithmId");
            String algorithmClassName = (String) data.get("algorithmClassName");
            String componentId = (String) data.get("componentId");
            String componentName = (String) data.get("componentName");

            // 1. 处理变电站节点（根节点）
            TreeNode stationNode = nodeMap.computeIfAbsent(stationCode, k -> {
                TreeNode node = new TreeNode(stationCode, stationName,null);
                roots.add(node); // 添加为根节点
                return node;
            });

            if (StrUtil.isNotBlank(algorithmId)) {
                // 2. 处理算法节点（第二层）
                // 使用复合键：stationKey + ":" + algorithmId 确保唯一性
                String algorithmKey = stationCode + ":" + algorithmId;
                TreeNode algorithmNode = nodeMap.computeIfAbsent(algorithmKey, k -> {
                    TreeNode node = new TreeNode(algorithmId, algorithmClassName,stationCode);
                    stationNode.getChildren().add(node); // 挂载到变电站节点下
                    return node;
                });

                if (StrUtil.isNotBlank(componentId)) {
                    // 3. 处理组件节点（第三层）
                    // 使用复合键：algorithmKey + ":" + componentId 确保唯一性
                    String componentKey = algorithmKey + ":" + componentId;
                    nodeMap.computeIfAbsent(componentKey, k -> {
                        TreeNode node = new TreeNode(componentId, componentName,algorithmId);
                        algorithmNode.getChildren().add(node); // 挂载到算法节点下
                        return node;
                    });
                }
            }
        }
        return roots;
    }
}
