package com.zksy.base.service.impl;

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.PipeNetworkBase;
import com.zksy.base.dto.PipeNetworkExportDTO;
import com.zksy.base.dto.PipeNetworkPageInDTO;
import com.zksy.base.mapper.PipeNetworkBaseMapper;
import com.zksy.base.service.PipeNetworkBaseService;
import com.zksy.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PipeNetworkBaseServiceImpl extends ServiceImpl<PipeNetworkBaseMapper, PipeNetworkBase>
        implements PipeNetworkBaseService {

    @Override
    public Page<PipeNetworkBase> queryByPage(PipeNetworkPageInDTO dto) {
        Page<PipeNetworkBase> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<PipeNetworkBase> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(dto.getNetworkName() != null && !dto.getNetworkName().isEmpty(), PipeNetworkBase::getNetworkName, dto.getNetworkName());
        wrapper.like(dto.getManagementUnit() != null && !dto.getManagementUnit().isEmpty(), PipeNetworkBase::getManagementUnit, dto.getManagementUnit());
        wrapper.eq(dto.getNetworkLevel() != null && !dto.getNetworkLevel().isEmpty(), PipeNetworkBase::getNetworkLevel, dto.getNetworkLevel());
        wrapper.like(dto.getMaterial() != null && !dto.getMaterial().isEmpty(), PipeNetworkBase::getMaterial, dto.getMaterial());
        wrapper.eq(dto.getStatus() != null && !dto.getStatus().isEmpty(), PipeNetworkBase::getStatus, dto.getStatus());
        wrapper.orderByDesc(PipeNetworkBase::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    public Page<PipeNetworkBase> findByPage(long pageNum, long pageSize,
                                             String networkCode, String networkName,
                                             String networkType, String status) {
        Page<PipeNetworkBase> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<PipeNetworkBase> queryWrapper = new LambdaQueryWrapper<>();
        if (networkCode != null && !networkCode.isEmpty()) {
            queryWrapper.like(PipeNetworkBase::getNetworkCode, networkCode);
        }
        if (networkName != null && !networkName.isEmpty()) {
            queryWrapper.like(PipeNetworkBase::getNetworkName, networkName);
        }
        if (networkType != null && !networkType.isEmpty()) {
            queryWrapper.eq(PipeNetworkBase::getNetworkType, networkType);
        }
        if (status != null && !status.isEmpty()) {
            queryWrapper.eq(PipeNetworkBase::getStatus, status);
        }
        queryWrapper.orderByDesc(PipeNetworkBase::getCreateTime);
        return this.page(page, queryWrapper);
    }

    @Override
    public boolean saveWithCheck(PipeNetworkBase entity) {
        LambdaQueryWrapper<PipeNetworkBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PipeNetworkBase::getNetworkCode, entity.getNetworkCode());
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new ServiceException("设施编码已存在，请更换：" + entity.getNetworkCode());
        }
        return this.save(entity);
    }

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

        for (PipeNetworkBase entity : entityList) {
            LambdaQueryWrapper<PipeNetworkBase> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PipeNetworkBase::getNetworkCode, entity.getNetworkCode());
            if (this.count(wrapper) > 0) {
                throw new ServiceException("设施编码已存在：" + entity.getNetworkCode());
            }
        }
        return this.saveBatch(entityList);
    }

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

        String newCode = entity.getNetworkCode();
        if (newCode != null) {
            LambdaQueryWrapper<PipeNetworkBase> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PipeNetworkBase::getNetworkCode, newCode)
                    .ne(PipeNetworkBase::getNetworkId, networkId);
            if (this.count(wrapper) > 0) {
                throw new ServiceException("设施编码已被使用：" + newCode);
            }
        }
        return this.updateById(entity);
    }

    @Override
    public List<PipeNetworkBase> getOptions() {
        LambdaQueryWrapper<PipeNetworkBase> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(PipeNetworkBase::getNetworkId, PipeNetworkBase::getNetworkName, PipeNetworkBase::getNetworkCode);
        wrapper.orderByAsc(PipeNetworkBase::getNetworkName);
        return this.list(wrapper);
    }

    @Override
    @Transactional
    public boolean removeWithCheck(String networkId) {
        PipeNetworkBase network = this.getById(networkId);
        if (network == null) {
            throw new ServiceException("设施不存在：" + networkId);
        }
        return this.removeById(networkId);
    }

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

        List<PipeNetworkBase> existNetworks = this.listByIds(networkIds);
        if (existNetworks.isEmpty()) {
            throw new ServiceException("批量删除失败：所有设施ID均不存在");
        }

        List<String> existIds = existNetworks.stream()
                .map(PipeNetworkBase::getNetworkId)
                .collect(Collectors.toList());

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

        return this.removeByIds(existIds);
    }

    @Override
    public List<PipeNetworkExportDTO> exportData(String networkName, String status) {
        LambdaQueryWrapper<PipeNetworkBase> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(networkName != null && !networkName.isEmpty(), PipeNetworkBase::getNetworkName, networkName);
        wrapper.eq(status != null && !status.isEmpty(), PipeNetworkBase::getStatus, status);
        wrapper.orderByDesc(PipeNetworkBase::getCreateTime);
        List<PipeNetworkBase> list = this.list(wrapper);

        List<PipeNetworkExportDTO> result = new ArrayList<>(list.size());
        for (PipeNetworkBase entity : list) {
            PipeNetworkExportDTO dto = new PipeNetworkExportDTO();
            dto.setNetworkCode(entity.getNetworkCode());
            dto.setNetworkName(entity.getNetworkName());
            dto.setNetworkTypeName(entity.getNetworkType());
            dto.setNetworkLevelName(entity.getNetworkLevel());
            dto.setManagementUnit(entity.getManagementUnit());
            dto.setMaterial(entity.getMaterial());
            dto.setLocation(entity.getLocation());
            dto.setLongitude(entity.getLongitude());
            dto.setLatitude(entity.getLatitude());
            dto.setLength(entity.getLength());
            dto.setDiameter(entity.getDiameter());
            dto.setStatusName(entity.getStatus());
            dto.setBuildDate(entity.getBuildDate());
            dto.setRemark(entity.getRemark());
            dto.setCreateTime(entity.getCreateTime());
            result.add(dto);
        }
        return result;
    }
}
