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.domain.EquipmentBase;
import com.zksy.base.domain.EquipmentMaintain;
import com.zksy.base.domain.EquipmentStatus;
import com.zksy.base.domain.EquipmentType;
import com.zksy.base.manhole.domain.ManholeData;
import com.zksy.base.manhole.mapper.ManholeDataMapper;
import com.zksy.base.mapper.EquipmentBaseMapper;
import com.zksy.base.mapper.EquipmentMaintainMapper;
import com.zksy.base.mapper.EquipmentStatusMapper;
import com.zksy.base.mapper.EquipmentTypeMapper;
import com.zksy.base.service.EquipmentBaseService;
import com.zksy.common.exception.ServiceException;
import com.zksy.manhole.dto.in.ManholeDevicePageInDTO;
import com.zksy.manhole.dto.out.EquipmentBaseOutDTO;
import com.zksy.manhole.dto.out.EquipmentStatusOutDTO;
import com.zksy.manhole.dto.out.ManholeDataOutDTO;
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.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 EquipmentBaseMapper equipmentBaseMapper;

    @Autowired
    private ManholeDataMapper manholeDataMapper;

    @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);
        }
        return this.page(page, queryWrapper);
    }

    /**
     * 新增仪器信息
     * @param entity
     * @return
     */
    @Override
    public boolean saveWithCheck(EquipmentBase entity) {
        String equipmentTypeId = entity.getEquipmentTypeId();
        EquipmentType equipmentType = equipmentTypeMapper.selectById(equipmentTypeId);
        if(equipmentType==null){
            throw new ServiceException("设备类型不存在，请检查equipment_type_id：");
        }
        //校验设备编码是否已存在
        LambdaQueryWrapper<EquipmentBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EquipmentBase::getEquipmentCode, entity.getEquipmentCode());
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new ServiceException("设备编码已存在，请更换：" + entity.getEquipmentCode());
        }
        return this.save(entity);
    }

    /**
     * 批量新增
     * @param entityList
     * @return
     */
    @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 (equipmentTypeMapper.selectById(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);
    }

    /**
     * 修改仪器信息
     * @param entity
     * @return
     */
    @Override
    @Transactional
    public boolean updateWithCheck(EquipmentBase entity) {
        //设备是否存在
        String equipmentId = entity.getEquipmentId();
        if (this.getById(equipmentId) == null) {
            throw new ServiceException("设备不存在，无法修改：" + equipmentId);
        }

        //修改设备类型ID，需要校验新类型是否存在
        String newTypeId = entity.getEquipmentTypeId();
        if (newTypeId != null && equipmentTypeMapper.selectById(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);
    }

    /**
     * 删除设备基础信息
     * @param equipmentId
     * @return
     */
    @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);

        //删除设备
        boolean deleted = this.baseMapper.deleteById(equipmentId) > 0;
        return deleted;
    }

    /**
     * 设备基础信息批量删除
     * @param equipmentIds
     * @return
     */
    @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均不存在");
        }
        // 提取存在的设备ID
        List<String> existIds = existEquipments.stream()
                .map(EquipmentBase::getEquipmentId)
                .collect(Collectors.toList());
        //无效ID
        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());
        //删除
        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::getProductionDate);
        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());
            List<EquipmentType> equipmentTypeList = equipmentTypeMapper.selectBatchIds(equipmentTypeIdList);
            Map<String, EquipmentType> equipmentTypeMap = new HashMap<>();
            if(CollUtil.isNotEmpty(equipmentTypeList)){
                equipmentTypeMap.putAll(equipmentTypeList.stream().collect(Collectors.toMap(EquipmentType::getTypeId, 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;
    }

}
