package com.zksy.base.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.base.alarm.domain.WarningThreshold;
import com.zksy.base.alarm.mapper.WarningThresholdMapper;
import com.zksy.base.domain.*;
import com.zksy.base.domain.vo.EquipmentFullVO;
import com.zksy.base.manhole.domain.ManholeData;
import com.zksy.base.manhole.mapper.ManholeDataMapper;
import com.zksy.base.mapper.*;
import com.zksy.base.service.EquipmentBaseService;
import com.zksy.common.exception.ServiceException;
import com.zksy.manhole.dto.in.EquipmentCountByTypeInDTO;
import com.zksy.manhole.dto.in.EquipmentExportInDTO;
import com.zksy.manhole.dto.in.ManholeDeviceListInDTO;
import com.zksy.manhole.dto.in.ManholeDevicePageInDTO;
import com.zksy.manhole.dto.out.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EquipmentBaseServiceImpl extends ServiceImpl<EquipmentBaseMapper, EquipmentBase>
        implements EquipmentBaseService {

    @Autowired
    private EquipmentTypeMapper equipmentTypeMapper;

    @Autowired
    private EquipmentMaintainMapper equipmentMaintainMapper;

    @Autowired
    private EquipmentStatusMapper equipmentStatusMapper;

    @Autowired
    private EquipmentPointRelMapper equipmentPointRelMapper;

    @Autowired
    private EquipmentTestMapper equipmentTestMapper;

    @Autowired
    private WarningThresholdMapper warningThresholdMapper;

    @Autowired
    private ManholeDataMapper manholeDataMapper;

    @Autowired
    private GasPipePointDeviceRelMapper gasPipePointDeviceRelMapper;

    @Autowired
    private GasPipePointMapper gasPipePointMapper;

    @Autowired
    private PipeNetworkBaseMapper pipeNetworkBaseMapper;

    @Override
    public Page<EquipmentBase> findByPage(long pageNum, long pageSize,
                                          String equipmentCode, String equipmentName,
                                          String equipmentModel, String manufacturer) {
        Page<EquipmentBase> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<EquipmentBase> queryWrapper = new LambdaQueryWrapper<>();
        if (equipmentCode != null && !equipmentCode.isEmpty()) {
            queryWrapper.like(EquipmentBase::getEquipmentCode, equipmentCode);
        }
        if (equipmentName != null && !equipmentName.isEmpty()) {
            queryWrapper.like(EquipmentBase::getEquipmentName, equipmentName);
        }
        if (equipmentModel != null && !equipmentModel.isEmpty()) {
            queryWrapper.like(EquipmentBase::getEquipmentModel, equipmentModel);
        }
        if (manufacturer != null && !manufacturer.isEmpty()) {
            queryWrapper.like(EquipmentBase::getManufacturer, manufacturer);
        }
        queryWrapper.orderByDesc(EquipmentBase::getCreateTime);
        return this.page(page, queryWrapper);
    }

    @Override
    public boolean saveWithCheck(EquipmentBase entity) {
        String equipmentTypeId = entity.getEquipmentTypeId();
        EquipmentType equipmentType = getEquipmentTypeById(equipmentTypeId);
        if (equipmentType == null) {
            throw new ServiceException("设备类型不存在，请检查equipment_type_id：" + equipmentTypeId);
        }
        LambdaQueryWrapper<EquipmentBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EquipmentBase::getEquipmentCode, entity.getEquipmentCode());
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new ServiceException("设备编码已存在，请更换：" + entity.getEquipmentCode());
        }
        try {
            return this.save(entity);
        } catch (org.springframework.dao.DataIntegrityViolationException e) {
            if (e.getMessage() != null && e.getMessage().contains("uk_equipment_code")) {
                throw new ServiceException("设备编码已存在, 请更换: " + entity.getEquipmentCode());
            }
            throw e;
        }
    }

    @Override
    public boolean saveBatchWithCheck(List<EquipmentBase> entityList) {
        Set<String> codeSet = new HashSet<>();
        for (EquipmentBase entity : entityList) {
            String code = entity.getEquipmentCode();
            if (codeSet.contains(code)) {
                throw new ServiceException("列表中存在重复编码：" + code);
            }
            codeSet.add(code);
        }

        for (EquipmentBase entity : entityList) {
            if (getEquipmentTypeById(entity.getEquipmentTypeId()) == null) {
                throw new ServiceException("设备类型不存在：" + entity.getEquipmentTypeId());
            }
            LambdaQueryWrapper<EquipmentBase> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(EquipmentBase::getEquipmentCode, entity.getEquipmentCode());
            if (this.count(wrapper) > 0) {
                throw new ServiceException("设备编码已存在：" + entity.getEquipmentCode());
            }
        }
        return this.saveBatch(entityList);
    }

    @Override
    @Transactional
    public boolean updateWithCheck(EquipmentBase entity) {
        String equipmentId = entity.getEquipmentId();
        if (this.getById(equipmentId) == null) {
            throw new ServiceException("设备不存在，无法修改：" + equipmentId);
        }

        String newTypeId = entity.getEquipmentTypeId();
        if (newTypeId != null && getEquipmentTypeById(newTypeId) == null) {
            throw new ServiceException("设备类型不存在：" + newTypeId);
        }

        String newCode = entity.getEquipmentCode();
        if (newCode != null) {
            LambdaQueryWrapper<EquipmentBase> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(EquipmentBase::getEquipmentCode, newCode)
                    .ne(EquipmentBase::getEquipmentId, equipmentId);
            if (this.count(wrapper) > 0) {
                throw new ServiceException("设备编码已被使用：" + newCode);
            }
        }
        return this.updateById(entity);
    }

    @Override
    @Transactional
    public boolean removeWithCheck(String equipmentId) {
        EquipmentBase equipment = this.getById(equipmentId);
        if (equipment == null) {
            throw new ServiceException("设备不存在：" + equipmentId);
        }

        LambdaQueryWrapper<EquipmentMaintain> maintainWrapper = new LambdaQueryWrapper<>();
        maintainWrapper.eq(EquipmentMaintain::getEquipmentId, equipmentId);
        equipmentMaintainMapper.delete(maintainWrapper);
        log.info("已删除设备[{}]的维护记录", equipmentId);

        LambdaQueryWrapper<EquipmentStatus> statusWrapper = new LambdaQueryWrapper<>();
        statusWrapper.eq(EquipmentStatus::getEquipmentId, equipmentId);
        equipmentStatusMapper.delete(statusWrapper);
        log.info("已删除设备[{}]的状态记录", equipmentId);

        LambdaQueryWrapper<EquipmentPointRel> relWrapper = new LambdaQueryWrapper<>();
        relWrapper.eq(EquipmentPointRel::getEquipmentId, equipmentId);
        equipmentPointRelMapper.delete(relWrapper);
        log.info("已删除设备[{}]的监测点关联", equipmentId);

        // 现在 WarningThreshold 有了 equipmentId 字段，直接匹配
        /*LambdaQueryWrapper<WarningThreshold> thresholdWrapper = new LambdaQueryWrapper<>();
        thresholdWrapper.eq(WarningThreshold::getDeviceCode, equipment.getEquipmentCode());
        warningThresholdMapper.delete(thresholdWrapper);
        log.info("已删除设备[{}]的预警阈值配置", equipmentId);*/

        LambdaQueryWrapper<EquipmentTest> testWrapper = new LambdaQueryWrapper<>();
        testWrapper.eq(EquipmentTest::getEquipmentId, equipmentId);
        equipmentTestMapper.delete(testWrapper);
        log.info("已删除设备[{}]的测试记录", equipmentId);

        return this.baseMapper.deleteById(equipmentId) > 0;
    }

    @Override
    @Transactional
    public boolean removeBatchWithCheck(List<String> equipmentIds) {
        if (CollectionUtils.isEmpty(equipmentIds)) {
            throw new ServiceException("批量删除失败：设备ID列表不能为空");
        }

        List<EquipmentBase> existEquipments = this.listByIds(equipmentIds);
        if (existEquipments.isEmpty()) {
            throw new ServiceException("批量删除失败：所有设备ID均不存在");
        }
        List<String> existIds = existEquipments.stream()
                .map(EquipmentBase::getEquipmentId)
                .collect(Collectors.toList());

        List<String> invalidIds = equipmentIds.stream()
                .filter(id -> !existIds.contains(id))
                .collect(Collectors.toList());
        if (!invalidIds.isEmpty()) {
            log.warn("批量删除中存在无效设备ID：{}", invalidIds);
        }

        LambdaQueryWrapper<EquipmentMaintain> maintainWrapper = new LambdaQueryWrapper<>();
        maintainWrapper.in(EquipmentMaintain::getEquipmentId, existIds);
        equipmentMaintainMapper.delete(maintainWrapper);
        log.info("已批量删除{}条设备的维护记录", existIds.size());

        LambdaQueryWrapper<EquipmentStatus> statusWrapper = new LambdaQueryWrapper<>();
        statusWrapper.in(EquipmentStatus::getEquipmentId, existIds);
        equipmentStatusMapper.delete(statusWrapper);
        log.info("已批量删除{}条设备的状态记录", existIds.size());

        LambdaQueryWrapper<EquipmentPointRel> relWrapper = new LambdaQueryWrapper<>();
        relWrapper.in(EquipmentPointRel::getEquipmentId, existIds);
        equipmentPointRelMapper.delete(relWrapper);
        log.info("已批量删除{}条设备的监测点关联", existIds.size());

        // 现在 WarningThreshold 有了 equipmentId 字段，直接匹配
        /*LambdaQueryWrapper<WarningThreshold> thresholdWrapper = new LambdaQueryWrapper<>();
        thresholdWrapper.in(WarningThreshold::getEquipmentId, existIds);
        warningThresholdMapper.delete(thresholdWrapper);
        log.info("已批量删除{}条设备的预警阈值配置", existIds.size());*/

        LambdaQueryWrapper<EquipmentTest> testWrapper = new LambdaQueryWrapper<>();
        testWrapper.in(EquipmentTest::getEquipmentId, existIds);
        equipmentTestMapper.delete(testWrapper);
        log.info("已批量删除{}条设备的测试记录", existIds.size());

        return this.removeByIds(existIds);
    }

    /**
     * 分页查询监测设备台账列表
     * @param pageInDTO
     * @return
     */
    @Override
    public Page<EquipmentBaseOutDTO> findManholeDeviceByPage(ManholeDevicePageInDTO pageInDTO) {
        log.info("分页查询监测设备台账列表-入参:{}", pageInDTO);
        List<String> equipmentIds = null;
        if(pageInDTO.getCurrentStatus() != null){
            List<EquipmentStatus> equipmentStatusList = equipmentStatusMapper.selectList(new LambdaQueryWrapper<EquipmentStatus>()
                    .eq(EquipmentStatus::getCurrentStatus, pageInDTO.getCurrentStatus()));
            if(CollUtil.isEmpty(equipmentStatusList)){
                return new Page<>(pageInDTO.getPageNum(), pageInDTO.getPageSize(), 0);
            }
            equipmentIds = equipmentStatusList.stream().map(EquipmentStatus::getEquipmentId).distinct().collect(Collectors.toList());
        }
        Page<EquipmentBase> page = new Page<>(pageInDTO.getPageNum(), pageInDTO.getPageSize());
        LambdaQueryWrapper<EquipmentBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotEmpty(pageInDTO.getDeviceCode()), EquipmentBase::getEquipmentCode, pageInDTO.getDeviceCode())
                .eq(StringUtils.isNotEmpty(pageInDTO.getEquipmentTypeId()), EquipmentBase::getEquipmentTypeId, pageInDTO.getEquipmentTypeId())
                .in(CollUtil.isNotEmpty(equipmentIds), EquipmentBase::getEquipmentId, equipmentIds)
                .like(StringUtils.isNotEmpty(pageInDTO.getDeviceName()), EquipmentBase::getEquipmentName, pageInDTO.getDeviceName())
                .like(StringUtils.isNotEmpty(pageInDTO.getEquipmentLocation()), EquipmentBase::getEquipmentLocation, pageInDTO.getEquipmentLocation())
                .orderByDesc(EquipmentBase::getUpdateTime);
        Page<EquipmentBase> rs = this.page(page, queryWrapper);
        List<EquipmentBaseOutDTO> outDTOList = BeanUtil.copyToList(rs.getRecords(), EquipmentBaseOutDTO.class);
        if (CollUtil.isNotEmpty(outDTOList)) {
            //查询设备类型
            List<String> equipmentTypeIdList = outDTOList.stream().map(EquipmentBaseOutDTO::getEquipmentTypeId).distinct().collect(Collectors.toList());
            LambdaQueryWrapper<EquipmentType> batchQw = new LambdaQueryWrapper<>();
            batchQw.in(EquipmentType::getId, equipmentTypeIdList);
            List<EquipmentType> equipmentTypeList = equipmentTypeMapper.selectList(batchQw);
            Map<String, EquipmentType> equipmentTypeMap = new HashMap<>();
            if(CollUtil.isNotEmpty(equipmentTypeList)){
                equipmentTypeMap.putAll(equipmentTypeList.stream().collect(
                    Collectors.toMap(t -> String.valueOf(t.getId()), Function.identity(), (key1, key2) -> key2)));
            }
            //查询设备状态
            List<String> equipmentIdList = outDTOList.stream().map(EquipmentBaseOutDTO::getEquipmentId).distinct().collect(Collectors.toList());
            List<EquipmentStatus> equipmentStatusList = equipmentStatusMapper.selectList(new LambdaQueryWrapper<EquipmentStatus>()
                    .in(EquipmentStatus::getEquipmentId, equipmentIdList));
            Map<String, EquipmentStatus> EquipmentStatusMap = new HashMap<>();
            if(CollUtil.isNotEmpty(equipmentStatusList)){
                EquipmentStatusMap.putAll(equipmentStatusList.stream().collect(Collectors.toMap(EquipmentStatus::getEquipmentId, Function.identity(), (key1, key2) -> key2)));
            }
            //查询设备监测状态
            Map<String, List<ManholeData>> imeiCardNumberMapList = new HashMap<>();
            if(pageInDTO.getIsQueryManholeData()){
                List<String> equipmentCodeList = outDTOList.stream().map(EquipmentBaseOutDTO::getEquipmentCode).distinct().collect(Collectors.toList());
                List<ManholeData> manholeDataList = manholeDataMapper.selectList(new LambdaQueryWrapper<ManholeData>()
                        .in(ManholeData::getImeiCardNumber, equipmentCodeList)
                        .orderByDesc(ManholeData::getCreateTime));
                imeiCardNumberMapList.putAll(manholeDataList.stream().collect(Collectors.groupingBy(ManholeData::getImeiCardNumber)));
            }
            List<ManholeData> manholeDataList = null;
            for(EquipmentBaseOutDTO outDTO : outDTOList) {
                EquipmentType equipmentType = equipmentTypeMap.get(outDTO.getEquipmentTypeId());
                if(equipmentType != null){
                    outDTO.setEquipmentTypeName(equipmentType.getTypeName());
                }
                EquipmentStatus equipmentStatus = EquipmentStatusMap.get(outDTO.getEquipmentId());
                if(equipmentStatus != null){
                    EquipmentStatusOutDTO equipmentStatusOutDTO = BeanUtil.copyProperties(equipmentStatus, EquipmentStatusOutDTO.class);
                    outDTO.setEquipmentStatus(equipmentStatusOutDTO);
                }
                if(pageInDTO.getIsQueryManholeData()){
                    manholeDataList = imeiCardNumberMapList.get(outDTO.getEquipmentCode());
                    if(CollUtil.isNotEmpty(manholeDataList)){
                        ManholeData manholeData = manholeDataList.get(0);
                        ManholeDataOutDTO manholeDataOutDTO = BeanUtil.copyProperties(manholeData, ManholeDataOutDTO.class);
                        outDTO.setManholeData(manholeDataOutDTO);
                    }
                }
            }
        }
        Page<EquipmentBaseOutDTO> outPage = new Page<>(pageInDTO.getPageNum(), pageInDTO.getPageSize(), rs.getTotal());
        outPage.setRecords(outDTOList);
        return outPage;
    }

    /**
     * 查询井盖监测设备列表
     * @param listInDTO
     * @return
     */
    @Override
    public List<EquipmentBaseOutDTO> getManholeDataList(ManholeDeviceListInDTO listInDTO) {
        log.info("查询井盖监测设备列表-入参:{}", listInDTO);
        List<String> equipmentIds = null;
        if(listInDTO.getCurrentStatus() != null || listInDTO.getAlarmStatus() != null || listInDTO.getOnlineStatus() != null){
            List<EquipmentStatus> equipmentStatusList = equipmentStatusMapper.selectList(new LambdaQueryWrapper<EquipmentStatus>()
                    .eq(listInDTO.getCurrentStatus() != null, EquipmentStatus::getCurrentStatus, listInDTO.getCurrentStatus())
                    .eq(listInDTO.getAlarmStatus() != null, EquipmentStatus::getAlarmStatus, listInDTO.getAlarmStatus())
                    .eq(listInDTO.getOnlineStatus() != null, EquipmentStatus::getOnlineStatus, listInDTO.getOnlineStatus()));
            if(CollUtil.isEmpty(equipmentStatusList)){
                return new ArrayList<>();
            }
            equipmentIds = equipmentStatusList.stream().map(EquipmentStatus::getEquipmentId).distinct().collect(Collectors.toList());
        }
        LambdaQueryWrapper<EquipmentBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CollUtil.isNotEmpty(equipmentIds), EquipmentBase::getEquipmentId, equipmentIds)
                .and(StringUtils.isNotBlank(listInDTO.getKeyword()), wrapper -> wrapper
                        .like(EquipmentBase::getEquipmentCode, listInDTO.getKeyword())
                        .or()
                        .like(EquipmentBase::getEquipmentName, listInDTO.getKeyword())
                        .or()
                        .like(EquipmentBase::getEquipmentLocation, listInDTO.getKeyword()))
                .orderByDesc(EquipmentBase::getUpdateTime);
        List<EquipmentBase> equipmentBaseList = this.list(queryWrapper);
        if (CollUtil.isEmpty(equipmentBaseList)) {
            return new ArrayList<>();
        }
        List<EquipmentBaseOutDTO> outDTOList = BeanUtil.copyToList(equipmentBaseList, EquipmentBaseOutDTO.class);
        //查询设备类型
        List<String> equipmentTypeIdList = outDTOList.stream().map(EquipmentBaseOutDTO::getEquipmentTypeId).distinct().collect(Collectors.toList());
        LambdaQueryWrapper<EquipmentType> batchQw = new LambdaQueryWrapper<>();
        batchQw.in(EquipmentType::getId, equipmentTypeIdList);
        List<EquipmentType> equipmentTypeList = equipmentTypeMapper.selectList(batchQw);
        Map<String, EquipmentType> equipmentTypeMap = new HashMap<>();
        if(CollUtil.isNotEmpty(equipmentTypeList)){
            equipmentTypeMap.putAll(equipmentTypeList.stream().collect(
                Collectors.toMap(t -> String.valueOf(t.getId()), Function.identity(), (key1, key2) -> key2)));
        }
        //查询设备状态
        List<String> equipmentIdList = outDTOList.stream().map(EquipmentBaseOutDTO::getEquipmentId).distinct().collect(Collectors.toList());
        List<EquipmentStatus> equipmentStatusList = equipmentStatusMapper.selectList(new LambdaQueryWrapper<EquipmentStatus>()
                .in(EquipmentStatus::getEquipmentId, equipmentIdList));
        Map<String, EquipmentStatus> EquipmentStatusMap = new HashMap<>();
        if(CollUtil.isNotEmpty(equipmentStatusList)){
            EquipmentStatusMap.putAll(equipmentStatusList.stream().collect(Collectors.toMap(EquipmentStatus::getEquipmentId, Function.identity(), (key1, key2) -> key2)));
        }
        //查询设备监测状态
        Map<String, List<ManholeData>> imeiCardNumberMapList = new HashMap<>();
        if(listInDTO.getIsQueryManholeData()){
            List<String> equipmentCodeList = outDTOList.stream().map(EquipmentBaseOutDTO::getEquipmentCode).distinct().collect(Collectors.toList());
            List<ManholeData> manholeDataList = manholeDataMapper.selectList(new LambdaQueryWrapper<ManholeData>()
                    .in(ManholeData::getImeiCardNumber, equipmentCodeList)
                    .orderByDesc(ManholeData::getCreateTime));
            imeiCardNumberMapList.putAll(manholeDataList.stream().collect(Collectors.groupingBy(ManholeData::getImeiCardNumber)));
        }
        List<ManholeData> manholeDataList = null;
        for(EquipmentBaseOutDTO outDTO : outDTOList) {
            EquipmentType equipmentType = equipmentTypeMap.get(outDTO.getEquipmentTypeId());
            if(equipmentType != null){
                outDTO.setEquipmentTypeName(equipmentType.getTypeName());
            }
            EquipmentStatus equipmentStatus = EquipmentStatusMap.get(outDTO.getEquipmentId());
            if(equipmentStatus != null){
                EquipmentStatusOutDTO equipmentStatusOutDTO = BeanUtil.copyProperties(equipmentStatus, EquipmentStatusOutDTO.class);
                outDTO.setEquipmentStatus(equipmentStatusOutDTO);
            }
            if(listInDTO.getIsQueryManholeData()){
                manholeDataList = imeiCardNumberMapList.get(outDTO.getEquipmentCode());
                if(CollUtil.isNotEmpty(manholeDataList)){
                    ManholeData manholeData = manholeDataList.get(0);
                    ManholeDataOutDTO manholeDataOutDTO = BeanUtil.copyProperties(manholeData, ManholeDataOutDTO.class);
                    outDTO.setManholeData(manholeDataOutDTO);
                }
            }
        }
        return outDTOList;
    }

    @Override
    @Transactional
    public boolean updateEquipmentStatus(String equipmentId, Integer currentStatus) {
        EquipmentBase equipment = this.getById(equipmentId);
        if (equipment == null) {
            throw new ServiceException("设备不存在：" + equipmentId);
        }

        LambdaQueryWrapper<EquipmentStatus> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentStatus::getEquipmentId, equipmentId);
        EquipmentStatus status = equipmentStatusMapper.selectOne(wrapper);

        if (status == null) {
            status = new EquipmentStatus();
            status.setEquipmentId(equipmentId);
            status.setCurrentStatus(currentStatus);
            status.setAlarmStatus(0);
            status.setOnlineStatus(1);
            status.setStatusUpdateTime(LocalDateTime.now());
            return equipmentStatusMapper.insert(status) > 0;
        } else {
            status.setCurrentStatus(currentStatus);
            status.setStatusUpdateTime(LocalDateTime.now());
            return equipmentStatusMapper.updateById(status) > 0;
        }
    }

    @Override
    @Transactional
    public boolean testEquipment(String equipmentId, String testType, String testDetail, String testUser) {
        EquipmentBase equipment = this.getById(equipmentId);
        if (equipment == null) {
            throw new ServiceException("设备不存在：" + equipmentId);
        }

        EquipmentTest test = new EquipmentTest();
        test.setEquipmentId(equipmentId);
        test.setTestType(testType);
        test.setTestResult("SUCCESS");
        test.setTestDetail(testDetail);
        test.setTestTime(LocalDateTime.now());
        test.setTestUser(testUser);
        return equipmentTestMapper.insert(test) > 0;
    }

    @Override
    public Map<String, Object> getEquipmentDetail(String equipmentId) {
        EquipmentBase equipment = this.getById(equipmentId);
        if (equipment == null) {
            throw new ServiceException("设备不存在：" + equipmentId);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("equipmentInfo", equipment);

        if (equipment.getEquipmentTypeId() != null) {
            EquipmentType type = getEquipmentTypeById(equipment.getEquipmentTypeId());
            result.put("typeInfo", type);
        }

        LambdaQueryWrapper<EquipmentStatus> statusWrapper = new LambdaQueryWrapper<>();
        statusWrapper.eq(EquipmentStatus::getEquipmentId, equipmentId);
        EquipmentStatus status = equipmentStatusMapper.selectOne(statusWrapper);
        result.put("statusInfo", status);

        LambdaQueryWrapper<EquipmentMaintain> maintainWrapper = new LambdaQueryWrapper<>();
        maintainWrapper.eq(EquipmentMaintain::getEquipmentId, equipmentId);
        maintainWrapper.orderByDesc(EquipmentMaintain::getMaintainDate);
        List<EquipmentMaintain> maintainList = equipmentMaintainMapper.selectList(maintainWrapper);
        result.put("maintainList", maintainList);

        LambdaQueryWrapper<EquipmentPointRel> relWrapper = new LambdaQueryWrapper<>();
        relWrapper.eq(EquipmentPointRel::getEquipmentId, equipmentId);
        List<EquipmentPointRel> relList = equipmentPointRelMapper.selectList(relWrapper);
        result.put("pointRelList", relList);

        // 现在 WarningThreshold 有了 equipmentId 字段，直接匹配
        LambdaQueryWrapper<WarningThreshold> thresholdWrapper = new LambdaQueryWrapper<>();
        thresholdWrapper.eq(WarningThreshold::getDeviceCode, equipment.getEquipmentCode());
        List<WarningThreshold> thresholdList = warningThresholdMapper.selectList(thresholdWrapper);
        result.put("thresholdList", thresholdList);

        LambdaQueryWrapper<EquipmentTest> testWrapper = new LambdaQueryWrapper<>();
        testWrapper.eq(EquipmentTest::getEquipmentId, equipmentId);
        testWrapper.orderByDesc(EquipmentTest::getTestTime);
        List<EquipmentTest> testList = equipmentTestMapper.selectList(testWrapper);
        result.put("testList", testList);

        return result;
    }

    @Override
    public Page<EquipmentFullVO> findFullByPage(long pageNum, long pageSize,
                                                String equipmentCode, String equipmentName,
                                                String equipmentModel, String manufacturer,
                                                String equipmentTypeId) {
        // 1. 分页查询设备基础信息
        Page<EquipmentBase> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<EquipmentBase> qw = new LambdaQueryWrapper<>();
        if (equipmentCode != null && !equipmentCode.isEmpty()) {
            qw.like(EquipmentBase::getEquipmentCode, equipmentCode);
        }
        if (equipmentName != null && !equipmentName.isEmpty()) {
            qw.like(EquipmentBase::getEquipmentName, equipmentName);
        }
        if (equipmentModel != null && !equipmentModel.isEmpty()) {
            qw.like(EquipmentBase::getEquipmentModel, equipmentModel);
        }
        if (manufacturer != null && !manufacturer.isEmpty()) {
            qw.like(EquipmentBase::getManufacturer, manufacturer);
        }
        if (equipmentTypeId != null && !equipmentTypeId.isEmpty()) {
            // 查找该类型是否为父类（parent_type_id=0）
            LambdaQueryWrapper<EquipmentType> typeQw = new LambdaQueryWrapper<>();
            typeQw.eq(EquipmentType::getTypeId, equipmentTypeId);
            typeQw.eq(EquipmentType::getParentTypeId, "0");
            List<EquipmentType> parentTypes = equipmentTypeMapper.selectList(typeQw);

            if (parentTypes != null && !parentTypes.isEmpty()) {
                // 是父类，查找所有子类型的id
                EquipmentType parentType = parentTypes.get(0);
                LambdaQueryWrapper<EquipmentType> childQw = new LambdaQueryWrapper<>();
                childQw.eq(EquipmentType::getParentTypeId, String.valueOf(parentType.getId()));
                List<EquipmentType> childTypes = equipmentTypeMapper.selectList(childQw);
                List<String> typeIds = childTypes.stream()
                        .map(t -> String.valueOf(t.getId())).collect(Collectors.toList());
                typeIds.add(String.valueOf(parentType.getId())); // 也包含父类的id
                qw.in(EquipmentBase::getEquipmentTypeId, typeIds);
            } else {
                // 不是父类，直接精确匹配
                qw.eq(EquipmentBase::getEquipmentTypeId, equipmentTypeId);
            }
        }
        qw.orderByDesc(EquipmentBase::getCreateTime);
        Page<EquipmentBase> basePage = this.page(page, qw);
        List<EquipmentBase> equipmentList = basePage.getRecords();
        if (CollUtil.isEmpty(equipmentList)) {
            Page<EquipmentFullVO> emptyPage = new Page<>(pageNum, pageSize, 0);
            emptyPage.setRecords(new ArrayList<>());
            return emptyPage;
        }

        List<String> equipmentIds = equipmentList.stream()
                .map(EquipmentBase::getEquipmentId).collect(Collectors.toList());

        // 2. 批量查设备状态
        List<EquipmentStatus> statusList = equipmentStatusMapper.selectList(
                new LambdaQueryWrapper<EquipmentStatus>().in(EquipmentStatus::getEquipmentId, equipmentIds));
        Map<String, EquipmentStatus> statusMap = statusList.stream()
                .collect(Collectors.toMap(EquipmentStatus::getEquipmentId, Function.identity(), (a, b) -> a));

        // 3. 批量查管点-设备关联 (gas_pipe_point_device_rel)
        List<GasPipePointDeviceRel> allRels = gasPipePointDeviceRelMapper.selectList(
                new LambdaQueryWrapper<GasPipePointDeviceRel>().in(GasPipePointDeviceRel::getEquipmentId, equipmentIds));
        Map<String, GasPipePointDeviceRel> relMap = allRels.stream()
                .collect(Collectors.toMap(GasPipePointDeviceRel::getEquipmentId, Function.identity(), (a, b) -> a));

        // 4. 批量查管点
        List<Long> pointIds = allRels.stream().map(GasPipePointDeviceRel::getPointId).distinct().collect(Collectors.toList());
        Map<Long, GasPipePoint> pointMap = new HashMap<>();
        if (CollUtil.isNotEmpty(pointIds)) {
            List<GasPipePoint> pointList = gasPipePointMapper.selectBatchIds(pointIds);
            pointMap = pointList.stream()
                    .collect(Collectors.toMap(GasPipePoint::getPointId, Function.identity(), (a, b) -> a));
        }

        // 5. 批量查管线
        List<String> networkIds = pointMap.values().stream()
                .map(GasPipePoint::getNetworkId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<String, PipeNetworkBase> networkMap = new HashMap<>();
        if (CollUtil.isNotEmpty(networkIds)) {
            List<PipeNetworkBase> networkList = pipeNetworkBaseMapper.selectBatchIds(networkIds);
            networkMap = networkList.stream()
                    .collect(Collectors.toMap(PipeNetworkBase::getNetworkId, Function.identity(), (a, b) -> a));
        }

        // 批量查设备类型（用于解析类型名称）
        List<String> equipmentTypeIdList = equipmentList.stream()
                .map(EquipmentBase::getEquipmentTypeId)
                .filter(Objects::nonNull)
                .distinct().collect(Collectors.toList());
        Map<String, EquipmentType> equipmentTypeMap = new HashMap<>();
        if (CollUtil.isNotEmpty(equipmentTypeIdList)) {
            LambdaQueryWrapper<EquipmentType> batchTypeQw = new LambdaQueryWrapper<>();
            batchTypeQw.in(EquipmentType::getId, equipmentTypeIdList);
            List<EquipmentType> equipmentTypeList = equipmentTypeMapper.selectList(batchTypeQw);
            if (CollUtil.isNotEmpty(equipmentTypeList)) {
                equipmentTypeMap.putAll(equipmentTypeList.stream().collect(
                    Collectors.toMap(t -> String.valueOf(t.getId()), Function.identity(), (key1, key2) -> key2)));
            }
        }

        // 6. 组装VO
        List<EquipmentFullVO> voList = new ArrayList<>();
        for (EquipmentBase equip : equipmentList) {
            EquipmentFullVO vo = new EquipmentFullVO();
            BeanUtil.copyProperties(equip, vo);

            EquipmentStatus status = statusMap.get(equip.getEquipmentId());
            if (status != null) {
                vo.setCurrentStatus(status.getCurrentStatus());
                vo.setAlarmStatus(status.getAlarmStatus());
                vo.setOnlineStatus(status.getOnlineStatus());
                vo.setLastMaintainDate(status.getLastMaintainDate());
                vo.setNextMaintainDate(status.getNextMaintainDate());
            } else {
                vo.setCurrentStatus(1);
                vo.setAlarmStatus(0);
                vo.setOnlineStatus(0);
            }

            GasPipePointDeviceRel rel = relMap.get(equip.getEquipmentId());
            if (rel != null) {
                GasPipePoint point = pointMap.get(rel.getPointId());
                if (point != null) {
                    vo.setPointId(point.getPointId());
                    vo.setPointCode(point.getPointCode());
                    vo.setPointName(point.getPointName());
                    vo.setPointType(point.getPointType());
                    vo.setPointAddress(point.getAddress());

                    PipeNetworkBase network = networkMap.get(point.getNetworkId());
                    if (network != null) {
                        vo.setNetworkId(network.getNetworkId());
                        vo.setNetworkCode(network.getNetworkCode());
                        vo.setNetworkName(network.getNetworkName());
                        vo.setNetworkType(network.getNetworkType());
                        vo.setNetworkLevel(network.getNetworkLevel());
                    }
                }
            }

            voList.add(vo);

            // 解析设备类型名称
            EquipmentType eqType = equipmentTypeMap.get(equip.getEquipmentTypeId());
            if (eqType != null) {
                vo.setEquipmentTypeName(eqType.getTypeName());
            }
        }

        Page<EquipmentFullVO> resultPage = new Page<>(pageNum, pageSize, basePage.getTotal());
        resultPage.setRecords(voList);
        return resultPage;
    }

    @Override
    public List<EquipmentBase> getEquipmentByPoint(String pointId) {
        LambdaQueryWrapper<EquipmentPointRel> relWrapper = new LambdaQueryWrapper<>();
        relWrapper.eq(EquipmentPointRel::getPointId, pointId);
        List<EquipmentPointRel> relList = equipmentPointRelMapper.selectList(relWrapper);

        if (relList.isEmpty()) {
            return new ArrayList<>();
        }

        List<String> equipmentIds = relList.stream()
                .map(EquipmentPointRel::getEquipmentId)
                .collect(Collectors.toList());

        return this.listByIds(equipmentIds);
    }

    /**
     * 根据设备类别分组统计设备数量
     * @param inDTO
     * @return
     */
    @Override
    public List<EquipmentCountByTypeOutDTO> countByType(EquipmentCountByTypeInDTO inDTO) {
        log.info("根据设备类别分组统计设备数量-入参:{}", inDTO);
        String equipmentTypeId = inDTO.getEquipmentTypeId();
        List<EquipmentCountByTypeOutDTO> result = new ArrayList<>();
        if(StringUtils.isEmpty(equipmentTypeId)){
            // 设备类别ID为空：统计所有类别的设备数量
            List<EquipmentType> allTypes = equipmentTypeMapper.selectList(null);
            for(EquipmentType type : allTypes){
                long count = this.count(new LambdaQueryWrapper<EquipmentBase>()
                        .eq(EquipmentBase::getEquipmentTypeId, type.getId()));
                EquipmentCountByTypeOutDTO outDTO = new EquipmentCountByTypeOutDTO();
                outDTO.setEquipmentTypeId(type.getId());
                outDTO.setEquipmentTypeName(type.getTypeName());
                outDTO.setDeviceCount((int) count);
                result.add(outDTO);
            }
        } else {
            // 查询子类别
            List<EquipmentType> childTypes = equipmentTypeMapper.selectList(
                    new LambdaQueryWrapper<EquipmentType>()
                            .eq(EquipmentType::getParentTypeId, equipmentTypeId));
            if(CollUtil.isNotEmpty(childTypes)){
                // 有子类别：按子类别分组统计
                for(EquipmentType childType : childTypes){
                    long count = this.count(new LambdaQueryWrapper<EquipmentBase>()
                            .eq(EquipmentBase::getEquipmentTypeId, childType.getId()));
                    EquipmentCountByTypeOutDTO outDTO = new EquipmentCountByTypeOutDTO();
                    outDTO.setEquipmentTypeId(childType.getId());
                    outDTO.setEquipmentTypeName(childType.getTypeName());
                    outDTO.setDeviceCount((int) count);
                    result.add(outDTO);
                }
            } else {
                // 无子类别：直接统计该类别的设备数量
                EquipmentType equipmentType = getEquipmentTypeById(equipmentTypeId);
                long count = this.count(new LambdaQueryWrapper<EquipmentBase>()
                        .eq(EquipmentBase::getEquipmentTypeId, equipmentTypeId));
                EquipmentCountByTypeOutDTO outDTO = new EquipmentCountByTypeOutDTO();
                outDTO.setEquipmentTypeId(equipmentTypeId);
                outDTO.setEquipmentTypeName(equipmentType != null ? equipmentType.getTypeName() : null);
                outDTO.setDeviceCount((int) count);
                result.add(outDTO);
            }
        }
        return result;
    }

    /**
     * 导出设备明细数据
     * @param inDTO
     * @return
     */
    @Override
    public List<EquipmentExportOutDTO> exportEquipmentDetail(EquipmentExportInDTO inDTO) {
        log.info("导出设备明细数据-入参:{}", inDTO);
        LambdaQueryWrapper<EquipmentBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotEmpty(inDTO.getEquipmentTypeId()),
                EquipmentBase::getEquipmentTypeId, inDTO.getEquipmentTypeId())
                .orderByDesc(EquipmentBase::getCreateTime);
        List<EquipmentBase> equipmentList = this.list(queryWrapper);
        if(CollUtil.isEmpty(equipmentList)){
            return new ArrayList<>();
        }
        // 一次性查询所有设备类别
        List<String> typeIds = equipmentList.stream()
                .map(EquipmentBase::getEquipmentTypeId)
                .filter(StringUtils::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());
        Map<String, String> typeNameMap = new HashMap<>();
        if(CollUtil.isNotEmpty(typeIds)){
            List<EquipmentType> typeList = equipmentTypeMapper.selectBatchIds(typeIds);
            typeNameMap = typeList.stream()
                    .collect(Collectors.toMap(EquipmentType::getId, EquipmentType::getTypeName, (k1, k2) -> k1));
        }
        // 一次性查询所有设备状态
        List<String> equipmentIds = equipmentList.stream()
                .map(EquipmentBase::getEquipmentId)
                .collect(Collectors.toList());
        Map<String, EquipmentStatus> statusMap = new HashMap<>();
        if(CollUtil.isNotEmpty(equipmentIds)){
            List<EquipmentStatus> statusList = equipmentStatusMapper.selectList(
                    new LambdaQueryWrapper<EquipmentStatus>()
                            .in(EquipmentStatus::getEquipmentId, equipmentIds));
            statusMap = statusList.stream()
                    .collect(Collectors.toMap(EquipmentStatus::getEquipmentId, Function.identity(), (k1, k2) -> k1));
        }
        // 组装导出数据
        List<EquipmentExportOutDTO> result = new ArrayList<>();
        for(EquipmentBase equipment : equipmentList){
            EquipmentExportOutDTO outDTO = new EquipmentExportOutDTO();
            outDTO.setEquipmentCode(equipment.getEquipmentCode());
            outDTO.setEquipmentName(equipment.getEquipmentName());
            outDTO.setEquipmentLocation(equipment.getEquipmentLocation());
            outDTO.setInstallTime(equipment.getInstallTime());
            outDTO.setEquipmentTypeName(typeNameMap.get(equipment.getEquipmentTypeId()));
            EquipmentStatus equipmentStatus = statusMap.get(equipment.getEquipmentId());
            if(equipmentStatus != null){
                outDTO.setCurrentStatus(equipmentStatus.getCurrentStatus());
            }
            result.add(outDTO);
        }
        return result;
    }

    /**
     * 根据 typeId 查询设备类型，避免 selectOne 多结果异常
     * 原因：equipment_type 表中 type_id 存在重复记录，直接 selectById 会触发 TooManyResultsException
     * @return 找到的第一条记录，或 null
     */
    private EquipmentType getEquipmentTypeByTypeId(String typeId) {
        if (typeId == null) {
            return null;
        }
        LambdaQueryWrapper<EquipmentType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentType::getTypeId, typeId);
        wrapper.last("LIMIT 1");
        List<EquipmentType> list = equipmentTypeMapper.selectList(wrapper);
        return CollUtil.isNotEmpty(list) ? list.get(0) : null;
    }

    /**
     * 根据 id 查询设备类型（按数据库主键id查询）
     * @return 找到的第一条记录，或 null
     */
    private EquipmentType getEquipmentTypeById(String id) {
        if (id == null || id.isEmpty()) {
            return null;
        }
        LambdaQueryWrapper<EquipmentType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentType::getId, id);
        wrapper.last("LIMIT 1");
        List<EquipmentType> list = equipmentTypeMapper.selectList(wrapper);
        return CollUtil.isNotEmpty(list) ? list.get(0) : null;
    }

    @Override
    public List<EquipmentBase> findByTopLevelType(String typeName) {
        EquipmentType topType = equipmentTypeMapper.selectOne(
                new LambdaQueryWrapper<EquipmentType>()
                        .eq(EquipmentType::getTypeName, typeName)
                        .eq(EquipmentType::getParentTypeId, "0"));
        if (topType == null) {
            return new ArrayList<>();
        }

        List<String> typeIds = new ArrayList<>();
        List<EquipmentType> children = equipmentTypeMapper.selectList(
                new LambdaQueryWrapper<EquipmentType>()
                        .eq(EquipmentType::getParentTypeId, topType.getId()));
        for (EquipmentType child : children) {
            typeIds.add(child.getId());
        }
        LambdaQueryWrapper<EquipmentBase> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(EquipmentBase::getEquipmentTypeId, typeIds);
        wrapper.orderByDesc(EquipmentBase::getCreateTime);
        return this.list(wrapper);
    }
}
