package cn.iocoder.yudao.module.pms.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Node;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotTreeListReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotTreePageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.vo.IotTreeSaveReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotInfoClassifyDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.IotTreeDO;
import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.IotInfoClassifyMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.IotInfoMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.IotTreeMapper;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

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

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;

/**
 * pms树 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class IotTreeServiceImpl implements IotTreeService {

    @Resource
    private IotTreeMapper iotTreeMapper;
    @Autowired
    private DeptApi deptApi;
    @Autowired
    private IotDeviceService iotDeviceService;
    @Autowired
    private IotDeviceMapper iotDeviceMapper;
    @Autowired
    private IotInfoClassifyMapper iotInfoClassifyMapper;
    @Autowired
    private IotInfoMapper iotInfoMapper;
    @Resource
    private DeptService deptService;

    @Override
    public void initTreeCode() {
        List<IotTreeDO> iotTreeDOS = iotTreeMapper.selectList();
        List<IotTreeDO> devices = iotTreeDOS.stream().filter(e -> "device".equals(e.getType())).collect(Collectors.toList());
        Set<Long> ids = new HashSet<>();
//        if (Objects.nonNull(pageReqVO.getDeptId())) {
            ids = deptService.getChildDeptIdListFromCache(157L);
            ids.add(157L);
        IotDevicePageReqVO iotDevicePageReqVO = new IotDevicePageReqVO();
        List<Long> idds = new ArrayList<>(ids);
        iotDevicePageReqVO.setDeptIds((idds));
        List<Long> deviceIds = iotDeviceMapper.selectList(iotDevicePageReqVO).stream().map(IotDeviceDO::getId).collect(Collectors.toList());

        devices.forEach(device -> {
            if (deviceIds.contains(device.getOriginId())) {
                //更新设备资料库的名称
                IotDeviceDO iotDevice = iotDeviceService.getIotDevice(device.getOriginId());
                device.setName(iotDevice.getDeviceCode()+iotDevice.getDeviceName());

                //设备的部门id
                Long deptId = iotDevice.getDeptId();
                IotTreeListReqVO iotTreeListReqVO = new IotTreeListReqVO();
                iotTreeListReqVO.setOriginId(deptId);
                iotTreeListReqVO.setType("dept");
                List<IotTreeDO> iotTreeDOS1 = iotTreeMapper.selectList(iotTreeListReqVO);
                if (CollUtil.isNotEmpty(iotTreeDOS1)&&iotTreeDOS1.size()==1) {
                    if (!device.getParentId().equals(iotTreeDOS1.get(0).getId())) {
                        device.setParentId(iotTreeDOS1.get(0).getId());
                    }
                }
                iotTreeMapper.updateById(device);
            }
        });
    }

    @Override
    public List<IotTreeDO> getIotDeviceTree(Long deviceId) {
        IotTreeListReqVO reqVO = new IotTreeListReqVO();
        reqVO.setType("device");
        reqVO.setOriginId(deviceId);
        List<IotTreeDO> iotTreeDOS = iotTreeMapper.selectList(reqVO);
        return iotTreeDOS;
    }

    @Override
    public List<IotTreeDO> getIotTreeList(IotTreeListReqVO reqVO) {
        List<IotTreeDO> list = iotTreeMapper.selectList(reqVO);
        list.sort(Comparator.comparing(IotTreeDO::getSort));
        return list;
    }

    @Override
    public void addDeptDeal(DeptDO dept) {
        //插入pms树
        IotTreeDO iotTreeDO = new IotTreeDO();
        iotTreeDO.setType("dept");
        iotTreeDO.setOriginId(dept.getId());
        iotTreeDO.setName(dept.getName());
        iotTreeDO.setDeptId(dept.getId());
        List<IotTreeDO> iotTreeDOS = iotTreeMapper.selectListByOriginId(dept.getParentId(),"dept");
//        if (CollUtil.isNotEmpty(iotTreeDOS)) {
        iotTreeDO.setParentId(CollUtil.isNotEmpty(iotTreeDOS) ? iotTreeDOS.get(0).getId() : 0);
        iotTreeMapper.insert(iotTreeDO);
    }

    @Override
    public void updateDeptDeal(DeptDO updateObj) {
        //更新pms树
        List<IotTreeDO> iotTreeDOS = iotTreeMapper.selectListByOriginId(updateObj.getId(),"dept");
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(iotTreeDOS)) {
            throw new ServiceException(ErrorCodeConstants.DEPT_NOT_FOUND.getCode(),"无该部门");
        }
        IotTreeDO iotTreeDO = iotTreeDOS.get(0);
        iotTreeDO.setName(updateObj.getName());
        iotTreeDO.setDeptId(updateObj.getId());
        iotTreeMapper.updateById(iotTreeDO);
    }

    @Override
    public void deleteDeptDeal(String id) {
        //删除pms树
        iotTreeMapper.deleteByMap(ImmutableMap.of("origin_id", id));
    }


    @Override
    public Long createIotTree(IotTreeSaveReqVO createReqVO) {
        // 插入
        IotTreeDO iotTree = BeanUtils.toBean(createReqVO, IotTreeDO.class);
        if ("file".equals(createReqVO.getType())&&Objects.nonNull(createReqVO.getParentId())){

        }
        iotTreeMapper.insert(iotTree);
        // 返回
        return iotTree.getId();
    }

    @Override
    public void updateIotTree(IotTreeSaveReqVO updateReqVO) {
        // 校验存在
        validateIotTreeExists(updateReqVO.getId());
        // 更新
        IotTreeDO updateObj = BeanUtils.toBean(updateReqVO, IotTreeDO.class);
        iotTreeMapper.updateById(updateObj);
    }

    @Override
    public void deleteIotTree(Long id) {
        // 校验存在
        validateIotTreeExists(id);

        List<Long> childIds = getChildTreeList(ImmutableList.of(id)).stream().map(IotTreeDO::getId).collect(Collectors.toList());
        childIds.add(id);
        //删除iot的树形结构
        iotTreeMapper.deleteByIds(childIds);
        // 删除资料
        iotInfoMapper.deleteListByClassId(childIds);
    }

    private void validateIotTreeExists(Long id) {
        if (iotTreeMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.IOT_TREE_NOT_EXISTS);
        }
    }

    @Override
    public IotTreeDO getIotTree(Long id) {
        return iotTreeMapper.selectById(id);
    }

    @Override
    public PageResult<IotTreeDO> getIotTreePage(IotTreePageReqVO pageReqVO) {
        return iotTreeMapper.selectPage(pageReqVO);
    }


    @Override
    public List<IotTreeDO> getChildTreeList(Collection<Long> ids) {
        List<IotTreeDO> children = new LinkedList<>();
        // 遍历每一层
        Collection<Long> parentIds = ids;
        for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下，存在死循环
            // 查询当前层，所有的子产品分类
            List<IotTreeDO> depts = iotTreeMapper.selectListByParentId(parentIds);
            // 1. 如果没有子产品分类，则结束遍历
            if (CollUtil.isEmpty(depts)) {
                break;
            }
            // 2. 如果有子产品分类，继续遍历
            children.addAll(depts);
            parentIds = convertSet(depts, IotTreeDO::getId);
        }
        return children;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deviceAllotTree(List<Long> ids, Long targetDeptId) throws ServiceException {
        List<IotTreeDO> iotTreeDOS = iotTreeMapper.selectListByOriginId(targetDeptId,"dept");
        if (CollUtil.isEmpty(iotTreeDOS)) {throw new ServiceException(ErrorCodeConstants.IOT_TREE_NOT_EXISTS);}
        ids.forEach(id ->{
            List<IotTreeDO> device = iotTreeMapper.selectListByOriginId(id, "device");
            device.forEach(de -> de.setParentId(iotTreeDOS.get(0).getId()));
            iotTreeMapper.updateBatch(device);
        });
    }

    @Override
    public void initTree() {
        List<DeptRespDTO> deptList = deptApi.getDeptList();
        List<IotTreeDO> treeDOS = new ArrayList<>();
        deptList.forEach(dept -> {
            IotTreeDO iotTreeDO = new IotTreeDO();
            iotTreeDO.setOriginId(dept.getId());
            iotTreeDO.setType("dept");
            iotTreeDO.setName(dept.getName());
            iotTreeDO.setDeleted(false);
            iotTreeDO.setDeptId(dept.getId());
            treeDOS.add(iotTreeDO);
        });
        iotTreeMapper.insertBatch(treeDOS);

//        List<IotTreeDO> iotTreeDOS = iotTreeMapper.selectList();
        treeDOS.forEach(treeDO -> {
            Long parentId = deptList.stream().filter(dept -> treeDO.getOriginId().equals(dept.getId())).findFirst().get().getParentId();
            List<IotTreeDO> iotTreeDOS1 = iotTreeMapper.selectListByOriginId(parentId, "dept");
            if (CollUtil.isNotEmpty(iotTreeDOS1)) {
                treeDO.setParentId(iotTreeDOS1.get(0).getId());
            }
        });
        iotTreeMapper.updateBatch(treeDOS);

        List<IotDeviceDO> iotDeviceDOS = iotDeviceMapper.selectList();
        List<IotTreeDO> trees = new ArrayList<>();
        List<IotInfoClassifyDO> classifies = new ArrayList<>();
        iotDeviceDOS.forEach(deviceDO -> {
            Long deptId = deviceDO.getDeptId();
            List<IotTreeDO> iotTreeDOS = iotTreeMapper.selectListByOriginId(deptId, "dept");
//            if (CollUtil.isNotEmpty(iotTreeDOS)) {
                IotTreeDO iotTreeDO = new IotTreeDO();
                iotTreeDO.setOriginId(deviceDO.getId());
                iotTreeDO.setType("device");
                iotTreeDO.setName(deviceDO.getDeviceCode()+deviceDO.getDeviceName());
                iotTreeDO.setDeleted(false);
                iotTreeDO.setDeptId(deviceDO.getDeptId());
                iotTreeDO.setParentId(iotTreeDOS.get(0).getId());
                trees.add(iotTreeDO);
            IotInfoClassifyDO classifyDO = new IotInfoClassifyDO();
            classifyDO.setName(deviceDO.getDeviceCode()+deviceDO.getDeviceName()+"的设备资料");
            classifyDO.setDeviceId(deviceDO.getId());
            classifyDO.setParentId(0L);
            classifyDO.setStatus(0);
            classifyDO.setDeptId(deviceDO.getDeptId());
            classifies.add(classifyDO);
//            }
        });
        iotTreeMapper.insertBatch(trees);
        iotInfoClassifyMapper.insertBatch(classifies);

    }

    @Override
    public List<IotTreeDO> getAllParentIds(Long nodeId) {
        List<IotTreeDO> parents = new ArrayList<>();

        // 从当前节点开始向上查找所有父节点
        Long currentParentId = getParentId(nodeId);

        while (currentParentId != null) {
            IotTreeDO parentNode = iotTreeMapper.selectById(currentParentId);
            if (Objects.isNull(parentNode)) {
                break; // 父节点不存在时终止查找
            }
            parents.add(parentNode);
            currentParentId = parentNode.getParentId();
        }

        // 反转列表，使顶级父节点排在最前面
        Collections.reverse(parents);
        return parents;
    }

    private Long getParentId(Long nodeId) {
        IotTreeDO nodeOpt = iotTreeMapper.selectById(nodeId);
        return Objects.isNull(nodeOpt) ? null : nodeOpt.getParentId();
    }

}
