package com.huashe.park.core.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.huashe.common.utils.StringUtils;
import com.huashe.park.common.EnhancedIDGenerator;
import com.huashe.park.common.consts.enums.ConsStatus;
import com.huashe.park.core.mapper.PileMachineInfoMapper;
import com.huashe.park.core.redis.RedisProxy;
import com.huashe.park.core.service.IConsPileHoleInfoService;
import com.huashe.park.core.service.IConsUnitInfoService;
import com.huashe.park.core.service.IConsUnitMachineRelService;
import com.huashe.park.core.service.IPileMachineInfoService;
import com.huashe.park.core.service.IProjectCoordinateInfoService;
import com.huashe.park.domain.dto.cons.ConsPileHoleInfoVO;
import com.huashe.park.domain.dto.cons.ConstUnitNode;
import com.huashe.park.domain.dto.cons.MachineBiz;
import com.huashe.park.domain.dto.cons.MqttRequest;
import com.huashe.park.domain.entity.ConsPileHoleInfo;
import com.huashe.park.domain.entity.ConsUnitInfo;
import com.huashe.park.domain.entity.ConsUnitMachineRel;
import com.huashe.park.domain.entity.PileMachineInfo;
import com.huashe.park.domain.entity.ProjectCoordinateInfo;
import com.huashe.park.infrastructure.mqtt.CollectMqttService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.thread.ThreadUtil;

/**
 * 施工桩机信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-02-12
 */
@Service
public class PileMachineInfoServiceImpl implements IPileMachineInfoService {
    @Autowired
    private PileMachineInfoMapper pileMachineInfoMapper;

    @Autowired
    private IConsUnitInfoService consUnitInfoService;

    @Autowired
    private IConsUnitMachineRelService consUnitMachineRelService;

    @Autowired
    private IConsPileHoleInfoService pileHoleInfoService;

    @Autowired
    private IProjectCoordinateInfoService projectCoordinateInfoService;

    @Autowired
    private EnhancedIDGenerator byte8Id;

    @Autowired
    private RedisProxy redisProxy;

    @Resource
    private CollectMqttService collectMqttService;

    private static final String CACHE_KEY = "consPileMachineInfo:byteId:%s";

    /**
     * 查询施工桩机信息
     * 
     * @param id 施工桩机信息主键
     * @return 施工桩机信息
     */
    @Override
    public PileMachineInfo selectPileMachineInfoById(Long id) {
        return pileMachineInfoMapper.selectPileMachineInfoById(id);
    }

    @Override
    public PileMachineInfo selectPileMachineInfoByByteId(String byteId) {
        String redisKey = String.format(CACHE_KEY, byteId);
        if (redisProxy.hasKey(redisKey)) {
            return redisProxy.getCacheObject(redisKey);
        }
        PileMachineInfo pileMachineInfo = pileMachineInfoMapper.selectPileMachineInfoByByteId(byteId);
        if (ObjectUtils.isNotEmpty(pileMachineInfo)) {
            redisProxy.setCacheObject(redisKey, pileMachineInfo);
        }
        return pileMachineInfo;
    }

    /**
     * 查询施工桩机信息列表
     * 
     * @param pileMachineInfo 施工桩机信息
     * @return 施工桩机信息
     */
    @Override
    public List<PileMachineInfo> selectPileMachineInfoList(PileMachineInfo pileMachineInfo) {
        return pileMachineInfoMapper.selectPileMachineInfoList(pileMachineInfo);
    }

    /**
     * 新增施工桩机信息
     * 
     * @param pileMachineInfo 施工桩机信息
     * @return 结果
     */
    @Override
    public int insertPileMachineInfo(PileMachineInfo pileMachineInfo) {
        pileMachineInfo.setPwd(pileMachineInfo.getSn() + "381.2371");
        pileMachineInfo.setByteId(byte8Id.generate());
        int i = pileMachineInfoMapper.insertPileMachineInfo(pileMachineInfo);
        if (i > 0) {
            ThreadUtil.execAsync(() -> {
                collectMqttService.newTopic(new MqttRequest() {
                    {
                        setClientKey(pileMachineInfo.getProductKey());
                        setClientSecret(pileMachineInfo.getDeviceSecret());
                        setTopic(pileMachineInfo.getTopic());
                    }
                });
            });
        }
        return i;
    }

    /**
     * 修改施工桩机信息
     * 
     * @param pileMachineInfo 施工桩机信息
     * @return 结果
     */
    @Override
    public int updatePileMachineInfo(PileMachineInfo pileMachineInfo) {
        return pileMachineInfoMapper.updatePileMachineInfo(pileMachineInfo);
    }

    @Override
    public int updatePileMachineInfoWidthPwd(PileMachineInfo pileMachineInfo) {
        pileMachineInfo.setPwd(pileMachineInfo.getSn() + "381.2371");
        return pileMachineInfoMapper.updatePileMachineInfo(pileMachineInfo);
    }

    /**
     * 批量删除施工桩机信息
     * 
     * @param ids 需要删除的施工桩机信息主键
     * @return 结果
     */
    @Override
    public int deletePileMachineInfoByIds(Long[] ids) {
        return pileMachineInfoMapper.deletePileMachineInfoByIds(ids);
    }

    /**
     * 删除施工桩机信息信息
     * 
     * @param id 施工桩机信息主键
     * @return 结果
     */
    @Override
    public int deletePileMachineInfoById(Long id) {
        return pileMachineInfoMapper.deletePileMachineInfoById(id);
    }

    @Override
    public List<PileMachineInfo> qryUnitMachine(Long consUnitId) {
        return pileMachineInfoMapper.qryUnitMachine(consUnitId);
    }

    @Override
    public List<ConstUnitNode> qryMachineAssignedUnit(String machineId) {
        PileMachineInfo pileMachineInfo = selectPileMachineInfoByByteId(machineId);
        List<ConsUnitInfo> consUnitInfos = consUnitInfoService.machineAssignedUnit(pileMachineInfo.getId());

        // 将 consUnitInfos 使用BeanUtils将子类转换成ConstUnitNode
        List<ConstUnitNode> constUnitNodes = new ArrayList<>();
        consUnitInfos.forEach((item) -> {
            ConstUnitNode constUnitNode = new ConstUnitNode();
            BeanUtils.copyProperties(item, constUnitNode);
            constUnitNodes.add(constUnitNode);
        });
        List<ConstUnitNode> tree = buildConsUnitTree(constUnitNodes);
        tree.forEach(item -> {
            List<ProjectCoordinateInfo> projectCoordinateInfos = projectCoordinateInfoService
                .selectProjectCoordinateInfoList(new ProjectCoordinateInfo() {
                    {
                        setProjectId(item.getProjectId());
                    }
                });
            ProjectCoordinateInfo projectCoordinateInfo = projectCoordinateInfos.get(0);
            item.setCoordinateModel(projectCoordinateInfo);
        });
        return tree;
    }

    @Override
    public List<ConsPileHoleInfoVO> machineUnitPileHole(MachineBiz machineBiz) {
        List<ConsPileHoleInfoVO> result = new ArrayList<>();
        ConsUnitInfo consUnitInfo = consUnitInfoService.selectConsUnitInfoByByteId(machineBiz.getDesignId());
        PileMachineInfo pileMachineInfo = selectPileMachineInfoByByteId(machineBiz.getMachineId());
        List<ConsUnitMachineRel> consUnitMachineRels = consUnitMachineRelService
            .selectConsUnitMachineRelList(new ConsUnitMachineRel() {
                {
                    setConsUnitId(consUnitInfo.getId());
                    setMachineId(pileMachineInfo.getId());
                }
            });
        if (CollectionUtils.isEmpty(consUnitMachineRels)) {
            return new ArrayList<>();
        }
        List<ConsPileHoleInfo> consPileHoleInfos = pileHoleInfoService
            .selectNonConsPileHoleInfo(new ConsPileHoleInfo() {
                {
                    setConsUnitId(consUnitInfo.getId());
                    setConsStatus(ConsStatus.CONS_STATUS_00.getCode());
                }
            });

        consPileHoleInfos.forEach(item -> {
            ConsPileHoleInfoVO consPileHoleInfoVO = new ConsPileHoleInfoVO();
            BeanUtil.copyProperties(item, consPileHoleInfoVO);
            result.add(consPileHoleInfoVO);
        });
        return result;
    }

    @Override
    public HashMap<String, Integer> cntMachineOnOffline() {
        return pileMachineInfoMapper.cntMachineOnOffline();
    }

    @Override
    public List<PileMachineInfo> selectMachineByConsUnitId(Long consUnitId) {
        return pileMachineInfoMapper.selectMachineByConsUnitId(consUnitId);
    }

    private List<ConstUnitNode> buildConsUnitTree(List<ConstUnitNode> consUnitInfos) {
        List<ConstUnitNode> returnList = new ArrayList<>();
        List<Long> tempList = consUnitInfos.stream().map(ConstUnitNode::getId).collect(Collectors.toList());
        for (ConstUnitNode dept : consUnitInfos) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(consUnitInfos, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = consUnitInfos;
        }
        return returnList;
    }

    private void recursionFn(List<ConstUnitNode> list, ConstUnitNode t) {
        // 得到子节点列表
        List<ConstUnitNode> childList = getChildList(list, t);
        t.setChild(childList);
        for (ConstUnitNode tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    private List<ConstUnitNode> getChildList(List<ConstUnitNode> list, ConstUnitNode t) {
        List<ConstUnitNode> tlist = new ArrayList<>();
        for (ConstUnitNode n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    private boolean hasChild(List<ConstUnitNode> list, ConstUnitNode t) {
        return !getChildList(list, t).isEmpty();
    }
}
