package com.zksy.drainage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.EquipmentPointRel;
import com.zksy.base.domain.MonitorPoint;
import com.zksy.base.mapper.EquipmentBaseMapper;
import com.zksy.base.mapper.EquipmentPointRelMapper;
import com.zksy.base.mapper.MonitorPointMapper;
import com.zksy.common.exception.ServiceException;
import com.zksy.drainage.service.DrainageEquipmentPointRelService;
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.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DrainageEquipmentPointRelServiceImpl extends ServiceImpl<EquipmentPointRelMapper, EquipmentPointRel>
        implements DrainageEquipmentPointRelService {

    @Autowired
    private EquipmentBaseMapper equipmentBaseMapper;

    @Autowired
    private MonitorPointMapper monitorPointMapper;

    @Override
    public Page<EquipmentPointRel> findByPage(long pageNum, long pageSize,
                                              String equipmentId, String pointId) {
        Page<EquipmentPointRel> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<EquipmentPointRel> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(equipmentId)) {
            wrapper.eq(EquipmentPointRel::getEquipmentId, equipmentId);
        }
        if (StringUtils.isNotBlank(pointId)) {
            wrapper.eq(EquipmentPointRel::getPointId, pointId);
        }
        wrapper.orderByDesc(EquipmentPointRel::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    @Transactional
    public boolean saveWithCheck(EquipmentPointRel entity) {
        String equipmentId = entity.getEquipmentId();
        if (StringUtils.isBlank(equipmentId)) {
            throw new ServiceException("设备ID不能为空");
        }
        if (equipmentBaseMapper.selectById(equipmentId) == null) {
            throw new ServiceException("关联的设备不存在：" + equipmentId);
        }
        String pointId = entity.getPointId();
        if (StringUtils.isBlank(pointId)) {
            throw new ServiceException("监测点ID不能为空");
        }
        if (monitorPointMapper.selectById(pointId) == null) {
            throw new ServiceException("关联的监测点不存在：" + pointId);
        }
        // 校验是否已存在相同关联
        LambdaQueryWrapper<EquipmentPointRel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentPointRel::getEquipmentId, equipmentId)
                .eq(EquipmentPointRel::getPointId, pointId);
        if (this.count(wrapper) > 0) {
            throw new ServiceException("该设备与监测点的关联关系已存在");
        }
        entity.setCreateTime(LocalDateTime.now());
        return this.save(entity);
    }

    @Override
    @Transactional
    public boolean saveBatchWithCheck(List<EquipmentPointRel> entityList) {
        Set<String> equipmentIds = entityList.stream()
                .map(EquipmentPointRel::getEquipmentId)
                .collect(Collectors.toSet());
        List<String> existEqIds = equipmentBaseMapper.selectBatchIds(equipmentIds).stream()
                .map(EquipmentBase::getEquipmentId)
                .collect(Collectors.toList());
        Set<String> invalidEqIds = equipmentIds.stream()
                .filter(id -> !existEqIds.contains(id))
                .collect(Collectors.toSet());
        if (!invalidEqIds.isEmpty()) {
            throw new ServiceException("存在无效的设备ID：" + invalidEqIds);
        }
        Set<String> pointIds = entityList.stream()
                .map(EquipmentPointRel::getPointId)
                .collect(Collectors.toSet());
        List<String> existPointIds = monitorPointMapper.selectBatchIds(pointIds).stream()
                .map(MonitorPoint::getPointId)
                .collect(Collectors.toList());
        Set<String> invalidPointIds = pointIds.stream()
                .filter(id -> !existPointIds.contains(id))
                .collect(Collectors.toSet());
        if (!invalidPointIds.isEmpty()) {
            throw new ServiceException("存在无效的监测点ID：" + invalidPointIds);
        }
        LocalDateTime now = LocalDateTime.now();
        entityList.forEach(e -> e.setCreateTime(now));
        return this.saveBatch(entityList);
    }

    @Override
    @Transactional
    public boolean removeWithCheck(String id) {
        if (this.getById(id) == null) {
            throw new ServiceException("关联记录不存在：" + id);
        }
        return this.removeById(id);
    }

    @Override
    @Transactional
    public boolean removeBatchWithCheck(List<String> ids) {
        return this.removeByIds(ids);
    }

    @Override
    public List<EquipmentPointRel> getByEquipmentId(String equipmentId) {
        LambdaQueryWrapper<EquipmentPointRel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentPointRel::getEquipmentId, equipmentId);
        return this.list(wrapper);
    }

    @Override
    public List<EquipmentPointRel> getByPointId(String pointId) {
        LambdaQueryWrapper<EquipmentPointRel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EquipmentPointRel::getPointId, pointId);
        return this.list(wrapper);
    }
}
