package org.dromara.facility.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.facility.constant.FacPhotovoltaicPanelPartsConstant;
import org.dromara.facility.constant.FacRedisKeyConstant;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.FacPhotovoltaicPanelColumn;
import org.dromara.facility.domain.FacPhotovoltaicPanelPoint;
import org.dromara.facility.domain.FacPhotovoltaicPanelSupport;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPoint;
import org.dromara.facility.domain.dto.photovoltaicpanelparts.FacPhotovoltaicPanelPartsCreateByGeoJsonReq;
import org.dromara.facility.domain.dto.photovoltaicpanelparts.FacPhotovoltaicPanelPartsCreateReq;
import org.dromara.facility.service.*;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.JSTUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author lcj
 * @date 2025/4/21 15:53
 */
@Slf4j
@Service
public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPanelPartsService {

    @Resource
    private IBusProjectService projectService;

    @Resource
    private IFacMatrixService matrixService;

    @Resource
    private IFacPhotovoltaicPanelService photovoltaicPanelService;

    @Resource
    private IFacPhotovoltaicPanelPointService photovoltaicPanelPointService;

    @Resource
    private IFacPhotovoltaicPanelColumnService photovoltaicPanelColumnService;

    @Resource
    private IFacPhotovoltaicPanelSupportService photovoltaicPanelSupportService;

    @Resource
    private IPgsProgressCategoryService progressCategoryService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private ScheduledExecutorService scheduledExecutorService;

    @Resource
    @Lazy
    private FacPhotovoltaicPanelPartsServiceImpl self; // 注入自己

    /**
     * 批量新增设施-光伏板（桩点、立柱、支架）
     *
     * @param geoJson GeoJson格式
     * @return 是否新增成功
     */
    @Override
    public Boolean insertPartsByGeoJson(FacPhotovoltaicPanelPartsCreateByGeoJsonReq geoJson) {
        // 设置 redis 防止多次操作
        String operationRedisKey = FacRedisKeyConstant.getInOperationByProjectRedisKey(geoJson.getProjectId());
        // 判断 redis key 是否存在，存在则返回
        Object object = redisTemplate.opsForValue().get(operationRedisKey);
        if (object != null && (Boolean) object) {
            throw new ServiceException("项目下桩点、立柱、支架数据正在处理中，请勿重复操作", HttpStatus.BAD_REQUEST);
        }
        // 第一次接收请求，进行数据校验
        int batchNum = geoJson.getBatchNum();
        if (batchNum == 1) {
            Long projectId = geoJson.getProjectId();
            if (projectService.getById(projectId) == null) {
                throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
            }
            // 查询项目下光伏板
            List<FacPhotovoltaicPanel> photovoltaicPanelList = photovoltaicPanelService.lambdaQuery()
                .eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
            if (CollUtil.isEmpty(photovoltaicPanelList)) {
                throw new ServiceException("项目下无光伏板信息，请先创建光伏板信息后再添加桩点、立柱、支架信息", HttpStatus.NOT_FOUND);
            }
        }
        // 获取 redis key
        String sessionId = geoJson.getSessionId();
        int totalBatch = geoJson.getTotalBatch();
        List<FacFeatureByPoint> dataList = geoJson.getLocationGeoJson().getFeatures();
        String redisKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, batchNum);
        // 存储到 Redis，设置过期时间 30 分钟
        redisTemplate.opsForValue().set(redisKey, dataList, 1800, TimeUnit.SECONDS);
        log.info("已接收第 {} 批数据，共 {} 批", batchNum, totalBatch);
        Long userId = LoginHelper.getUserId();
        SseMessageDto messageDto = new SseMessageDto();
        messageDto.setUserIds(List.of(userId));
        // 如果是最后一批，开始合并
        if (batchNum == totalBatch) {
            List<FacFeatureByPoint> allData = new ArrayList<>();
            for (int i = 1; i <= totalBatch; i++) {
                String batchKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, i);
                Object batch = redisTemplate.opsForValue().get(batchKey);
                if (batch instanceof List<?>) {
                    allData.addAll((List<FacFeatureByPoint>) batch);
                }
            }
            // 设置 redis key，防止多次操作
            redisTemplate.opsForValue().set(operationRedisKey, true);
            messageDto.setMessage("桩点、立柱、支架数据上传完毕，等待中");
            SseMessageUtils.publishMessage(messageDto);
            scheduledExecutorService.execute(() -> {
                try {
                    // 合并后的数据处理，如入库
                    this.saveBatch(geoJson.getProjectId(), allData, userId);
                } catch (Exception e) {
                    messageDto.setMessage("桩点、立柱、支架数据处理失败，请联系管理员处理");
                    SseMessageUtils.publishMessage(messageDto);
                    log.error("桩点、立柱、支架数据处理失败", e);
                    throw new ServiceException("桩点、立柱、支架数据处理失败", HttpStatus.ERROR);
                } finally {
                    // 清理缓存
                    for (int i = 1; i <= totalBatch; i++) {
                        String batchKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, i);
                        redisTemplate.delete(batchKey);
                    }
                    redisTemplate.delete(operationRedisKey);
                }
                messageDto.setMessage("桩点、立柱、支架数据处理完毕");
                SseMessageUtils.publishMessage(messageDto);
            });
            return true;
        }
        return true;
    }

    /**
     * 批量保存数据
     *
     * @param projectId 项目id
     * @param features  数据
     * @param userId    操作用户id
     */
    private void saveBatch(Long projectId, List<FacFeatureByPoint> features, Long userId) {
        // 查询项目下光伏板
        List<FacPhotovoltaicPanel> photovoltaicPanelList = photovoltaicPanelService.lambdaQuery()
            .eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
        // 获取数据库中所有点的列表
        List<FacPhotovoltaicPanelPoint> oldPointList = photovoltaicPanelPointService.lambdaQuery()
            .eq(FacPhotovoltaicPanelPoint::getProjectId, projectId).list();
        Map<String, FacPhotovoltaicPanelPoint> oldPointMap = oldPointList.stream()
            .collect(Collectors.toMap(
                FacPhotovoltaicPanelPoint::getName,
                Function.identity(),
                (existing, replacement) -> existing   // 如果有重复，保留第一个
            ));
        List<FacPhotovoltaicPanelColumn> oldColumnList = photovoltaicPanelColumnService.lambdaQuery()
            .eq(FacPhotovoltaicPanelColumn::getProjectId, projectId).list();
        Map<String, FacPhotovoltaicPanelColumn> oldColumnMap = oldColumnList.stream()
            .collect(Collectors.toMap(
                FacPhotovoltaicPanelColumn::getName,
                Function.identity(),
                (existing, replacement) -> existing   // 如果有重复，保留第一个
            ));
        List<FacPhotovoltaicPanelSupport> oldSupportList = photovoltaicPanelSupportService.lambdaQuery()
            .eq(FacPhotovoltaicPanelSupport::getProjectId, projectId).list();
        Map<String, FacPhotovoltaicPanelSupport> oldSupportMap = oldSupportList.stream()
            .collect(Collectors.toMap(
                FacPhotovoltaicPanelSupport::getName,
                Function.identity(),
                (existing, replacement) -> existing   // 如果有重复，保留第一个
            ));
        // 获取所有点列表
        List<List<Double>> pointPositionList = new ArrayList<>
            (features.stream().map(featureByPoint -> featureByPoint.getGeometry().getCoordinates()).toList());
        List<FacPhotovoltaicPanelPoint> pointList = new ArrayList<>();
        List<FacPhotovoltaicPanelColumn> columnList = new ArrayList<>();
        List<FacPhotovoltaicPanelSupport> supportList = new ArrayList<>();
        // 获取进度类别
        List<String> progressCategoryNameList = List.of(FacPhotovoltaicPanelPartsConstant.POINT,
            FacPhotovoltaicPanelPartsConstant.COLUMN,
            FacPhotovoltaicPanelPartsConstant.SUPPORT);
        Map<String, PgsProgressCategory> progressCategoryMap = progressCategoryService.lambdaQuery()
            .in(PgsProgressCategory::getName, progressCategoryNameList)
            .in(PgsProgressCategory::getProjectId, projectId, PgsProgressCategoryConstant.PUBLIC_PROJECT_ID)
            .list()
            .stream().collect(Collectors.toMap(
                PgsProgressCategory::getName,
                Function.identity(),
                (existing, replacement) -> existing
            ));
        // 遍历所有光伏板，找到所有匹配的点
        for (FacPhotovoltaicPanel photovoltaicPanel : photovoltaicPanelList) {
            String positions = photovoltaicPanel.getPositions();
            List<List<Double>> positionList = new ArrayList<>();
            List<String> arr = JSONUtil.toList(positions, String.class);
            for (String s : arr) {
                positionList.add(JSONUtil.toList(s, Double.class));
            }
            // 获取点在面内的点
            List<List<Double>> pointInPlaneList = JSTUtils.getPointInPlaneList(positionList, pointPositionList);
            // 删除点在面内的点
            pointPositionList.removeAll(pointInPlaneList);
            // 判断点在面内的点是否为空
            if (CollUtil.isNotEmpty(pointInPlaneList)) {
                int i = 1;
                // 遍历点在面内的点，添加实体信息
                for (List<Double> list : pointInPlaneList) {
                    String str = String.format("%02d", i);
                    String name = photovoltaicPanel.getName() + "." + str;
                    Long matrixId = photovoltaicPanel.getMatrixId();
                    String jsonStr = JSONUtil.toJsonStr(list);
                    FacPhotovoltaicPanelPoint photovoltaicPanelPoint = new FacPhotovoltaicPanelPoint();
                    photovoltaicPanelPoint.setProjectId(projectId);
                    photovoltaicPanelPoint.setMatrixId(matrixId);
                    photovoltaicPanelPoint.setName(name);
                    photovoltaicPanelPoint.setPositions(jsonStr);
                    photovoltaicPanelPoint.setCreateBy(userId);
                    photovoltaicPanelPoint.setUpdateBy(userId);
                    if (CollUtil.isNotEmpty(oldPointMap) && oldPointMap.containsKey(name)) {
                        FacPhotovoltaicPanelPoint oldPoint = oldPointMap.get(name);
                        photovoltaicPanelPoint.setFinishType(oldPoint.getFinishType());
                        photovoltaicPanelPoint.setStatus(oldPoint.getStatus());
                    }
                    if (CollUtil.isNotEmpty(progressCategoryMap) && progressCategoryMap.containsKey(FacPhotovoltaicPanelPartsConstant.POINT)) {
                        PgsProgressCategory progressCategory = progressCategoryMap.get(FacPhotovoltaicPanelPartsConstant.POINT);
                        photovoltaicPanelPoint.setProgressCategoryId(progressCategory.getId());
                        photovoltaicPanelPoint.setProgressCategoryName(progressCategory.getName());
                    }
                    pointList.add(photovoltaicPanelPoint);
                    FacPhotovoltaicPanelColumn photovoltaicPanelColumn = new FacPhotovoltaicPanelColumn();
                    photovoltaicPanelColumn.setProjectId(projectId);
                    photovoltaicPanelColumn.setMatrixId(matrixId);
                    photovoltaicPanelColumn.setName(name);
                    photovoltaicPanelColumn.setPositions(jsonStr);
                    photovoltaicPanelColumn.setCreateBy(userId);
                    photovoltaicPanelColumn.setUpdateBy(userId);
                    if (CollUtil.isNotEmpty(oldColumnMap) && oldColumnMap.containsKey(name)) {
                        FacPhotovoltaicPanelColumn oldColumn = oldColumnMap.get(name);
                        photovoltaicPanelColumn.setFinishType(oldColumn.getFinishType());
                        photovoltaicPanelColumn.setStatus(oldColumn.getStatus());
                    }
                    if (CollUtil.isNotEmpty(progressCategoryMap) && progressCategoryMap.containsKey(FacPhotovoltaicPanelPartsConstant.COLUMN)) {
                        PgsProgressCategory progressCategory = progressCategoryMap.get(FacPhotovoltaicPanelPartsConstant.COLUMN);
                        photovoltaicPanelColumn.setProgressCategoryId(progressCategory.getId());
                        photovoltaicPanelColumn.setProgressCategoryName(progressCategory.getName());
                    }
                    columnList.add(photovoltaicPanelColumn);
                    FacPhotovoltaicPanelSupport photovoltaicPanelSupport = new FacPhotovoltaicPanelSupport();
                    photovoltaicPanelSupport.setProjectId(projectId);
                    photovoltaicPanelSupport.setMatrixId(matrixId);
                    photovoltaicPanelSupport.setName(name);
                    photovoltaicPanelSupport.setPositions(jsonStr);
                    photovoltaicPanelSupport.setCreateBy(userId);
                    photovoltaicPanelSupport.setUpdateBy(userId);
                    if (CollUtil.isNotEmpty(oldSupportMap) && oldSupportMap.containsKey(name)) {
                        FacPhotovoltaicPanelSupport oldSupport = oldSupportMap.get(name);
                        photovoltaicPanelSupport.setFinishType(oldSupport.getFinishType());
                        photovoltaicPanelSupport.setStatus(oldSupport.getStatus());
                    }
                    if (CollUtil.isNotEmpty(progressCategoryMap) && progressCategoryMap.containsKey(FacPhotovoltaicPanelPartsConstant.SUPPORT)) {
                        PgsProgressCategory progressCategory = progressCategoryMap.get(FacPhotovoltaicPanelPartsConstant.SUPPORT);
                        photovoltaicPanelSupport.setProgressCategoryId(progressCategory.getId());
                        photovoltaicPanelSupport.setProgressCategoryName(progressCategory.getName());
                    }
                    supportList.add(photovoltaicPanelSupport);
                    i++;
                }
            }
        }
        // 自定义线程池（IO 密集型线程池）
        ThreadPoolExecutor customExecutor = new ThreadPoolExecutor(
            20,             // 核心线程数
            50,                        // 最大线程数
            60L,                       // 线程空闲存活时间
            TimeUnit.SECONDS,           // 存活时间单位
            new LinkedBlockingQueue<>(10000),  // 阻塞队列容量
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略：由调用线程处理任务
        );
        // 分批处理，避免长事务，假设每次处理 1000 条数据
        int batchSize = 1000;
        // 保存所有批次任务
        List<CompletableFuture<Void>> deleteFutures = new ArrayList<>();
        int deleteSize = oldPointList.size();
        for (int i = 0; i < deleteSize; i += batchSize) {
            int endIndex = Math.min(i + batchSize, deleteSize);
            List<FacPhotovoltaicPanelPoint> batchPointList = oldPointList.subList(i, endIndex);
            List<FacPhotovoltaicPanelColumn> batchColumnList = oldColumnList.subList(i, endIndex);
            List<FacPhotovoltaicPanelSupport> batchSupportList = oldSupportList.subList(i, endIndex);
            // 使用事务处理每批数据
            // 获取代理
            FacPhotovoltaicPanelPartsServiceImpl photovoltaicPanelPartsService = self;
            // 异步处理每批数据，将任务添加到异步任务列表
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelPartsService.batchDeletePartsInner(batchPointList, batchColumnList, batchSupportList), customExecutor);
            deleteFutures.add(future);
        }
        // 等待所有批次完成操作
        CompletableFuture.allOf(deleteFutures.toArray(new CompletableFuture[0])).join();
        // 保存所有批次任务
        List<CompletableFuture<Void>> insertFutures = new ArrayList<>();
        int totalSize = pointList.size();
        for (int i = 0; i < totalSize; i += batchSize) {
            int endIndex = Math.min(i + batchSize, totalSize);
            List<FacPhotovoltaicPanelPoint> batchPointList = pointList.subList(i, endIndex);
            List<FacPhotovoltaicPanelColumn> batchColumnList = columnList.subList(i, endIndex);
            List<FacPhotovoltaicPanelSupport> batchSupportList = supportList.subList(i, endIndex);
            // 使用事务处理每批数据
            // 获取代理
            FacPhotovoltaicPanelPartsServiceImpl photovoltaicPanelPartsService = self;
            // 异步处理每批数据，将任务添加到异步任务列表
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelPartsService.batchInsertPartsInner(batchPointList, batchColumnList, batchSupportList), customExecutor);
            insertFutures.add(future);
        }
        // 等待所有批次完成操作
        CompletableFuture.allOf(insertFutures.toArray(new CompletableFuture[0])).join();
        // 关闭线程池
        customExecutor.shutdown();
    }

    /**
     * 批量新增设施-光伏板（桩点、立柱、支架）内部方法
     *
     * @param pointList   桩点列表
     * @param columnList  立柱列表
     * @param supportList 支架列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchInsertPartsInner(List<FacPhotovoltaicPanelPoint> pointList,
                                      List<FacPhotovoltaicPanelColumn> columnList,
                                      List<FacPhotovoltaicPanelSupport> supportList) {
        try {
            if (CollUtil.isNotEmpty(pointList)) {
                boolean result = photovoltaicPanelPointService.saveBatch(pointList);
                if (!result) {
                    throw new ServiceException("批量新增光伏板桩点失败，数据库异常", HttpStatus.ERROR);
                }
            }
            if (CollUtil.isNotEmpty(columnList)) {
                boolean result = photovoltaicPanelColumnService.saveBatch(columnList);
                if (!result) {
                    throw new ServiceException("批量新增光伏板立柱失败，数据库异常", HttpStatus.ERROR);
                }
            }
            if (CollUtil.isNotEmpty(supportList)) {
                boolean result = photovoltaicPanelSupportService.saveBatch(supportList);
                if (!result) {
                    throw new ServiceException("批量新增光伏板支架失败，数据库异常", HttpStatus.ERROR);
                }
            }
        } catch (DataIntegrityViolationException e) {
            log.error("数据库唯一键冲突或违反其他完整性约束, 错误信息: {}", e.getMessage());
            throw new ServiceException("数据已存在，无法重复添加");
        } catch (DataAccessException e) {
            log.error("数据库连接问题、事务问题等导致操作失败, 错误信息: {}", e.getMessage());
            throw new ServiceException("数据库操作失败");
        } catch (Exception e) {
            // 捕获其他异常，做通用处理
            log.error("批量添加光伏板点时发生未知错误，错误信息: {}", e.getMessage());
            throw new ServiceException("批量添加光伏板点失败");
        }
    }

    /**
     * 批量删除设施-光伏板（桩点、立柱、支架）内部方法
     *
     * @param pointList   桩点列表
     * @param columnList  立柱列表
     * @param supportList 支架列表
     */
    @Override
    public void batchDeletePartsInner(List<FacPhotovoltaicPanelPoint> pointList,
                                      List<FacPhotovoltaicPanelColumn> columnList,
                                      List<FacPhotovoltaicPanelSupport> supportList) {
        try {
            if (CollUtil.isNotEmpty(pointList)) {
                boolean result = photovoltaicPanelPointService.removeBatchByIds(pointList);
                if (!result) {
                    throw new ServiceException("数据库操作失败", HttpStatus.ERROR);
                }
            }
            if (CollUtil.isNotEmpty(columnList)) {
                boolean result = photovoltaicPanelColumnService.removeBatchByIds(columnList);
                if (!result) {
                    throw new ServiceException("数据库操作失败", HttpStatus.ERROR);
                }
            }
            if (CollUtil.isNotEmpty(supportList)) {
                boolean result = photovoltaicPanelSupportService.removeBatchByIds(supportList);
                if (!result) {
                    throw new ServiceException("数据库操作失败", HttpStatus.ERROR);
                }
            }
        } catch (DataIntegrityViolationException e) {
            log.error("数据库唯一键冲突或违反其他完整性约束: {}", e.getMessage());
            throw new ServiceException("数据已存在，无法重复添加");
        } catch (DataAccessException e) {
            log.error("数据库连接问题、事务问题等导致操作失败: {}", e.getMessage());
            throw new ServiceException("数据库操作失败");
        } catch (Exception e) {
            // 捕获其他异常，做通用处理
            log.error("批量删除光伏板点时发生未知错误，错误信息: {}", e.getMessage());
            throw new ServiceException("批量添加光伏板点失败");
        }
    }

    /**
     * 批量新增设施-光伏板（桩点、立柱、支架）
     *
     * @param req 设施-光伏板（桩点、立柱、支架）
     * @return 是否新增成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertPartsByBatch(FacPhotovoltaicPanelPartsCreateReq req) {
        // 参数校验
        Long projectId = req.getProjectId();
        if (projectId == null || projectService.getById(projectId) == null) {
            throw new ServiceException("项目信息不存在", HttpStatus.NOT_FOUND);
        }
        Long matrixId = req.getMatrixId();
        if (matrixId == null || matrixService.getById(matrixId) == null) {
            throw new ServiceException("方阵信息不存在", HttpStatus.NOT_FOUND);
        }
        // 数据校验
        this.validName(projectId, req.getName());
        // 将实体类和 DTO 进行转换
        FacPhotovoltaicPanelPoint photovoltaicPanelPoint = new FacPhotovoltaicPanelPoint();
        BeanUtils.copyProperties(req, photovoltaicPanelPoint);
        FacPhotovoltaicPanelColumn photovoltaicPanelColumn = new FacPhotovoltaicPanelColumn();
        BeanUtils.copyProperties(req, photovoltaicPanelColumn);
        FacPhotovoltaicPanelSupport photovoltaicPanelSupport = new FacPhotovoltaicPanelSupport();
        BeanUtils.copyProperties(req, photovoltaicPanelSupport);
        // 填充默认值
        List<String> positionList = req.getPositionList();
        if (CollUtil.isNotEmpty(positionList)) {
            String jsonStr = JSONUtil.toJsonStr(positionList);
            photovoltaicPanelPoint.setPositions(jsonStr);
            photovoltaicPanelColumn.setPositions(jsonStr);
            photovoltaicPanelSupport.setPositions(jsonStr);
        }
        // 插入数据
        boolean pointSave = photovoltaicPanelPointService.save(photovoltaicPanelPoint);
        if (!pointSave) {
            throw new ServiceException("桩点信息插入失败", HttpStatus.ERROR);
        }
        boolean columnSave = photovoltaicPanelColumnService.save(photovoltaicPanelColumn);
        if (!columnSave) {
            throw new ServiceException("立柱信息插入失败", HttpStatus.ERROR);
        }
        boolean supportSave = photovoltaicPanelSupportService.save(photovoltaicPanelSupport);
        if (!supportSave) {
            throw new ServiceException("支架信息插入失败", HttpStatus.ERROR);
        }
        return true;
    }

    /**
     * 根据方阵主键判断是否存在光伏板点
     *
     * @param projectId 项目id
     * @param matrixIds 方阵Id列表
     * @return 是否存在
     */
    @Override
    public Boolean validPartsExistByMatrix(Long projectId, Collection<Long> matrixIds) {
        Long pointCount = photovoltaicPanelPointService.lambdaQuery()
            .eq(FacPhotovoltaicPanelPoint::getProjectId, projectId)
            .in(FacPhotovoltaicPanelPoint::getMatrixId, matrixIds)
            .count();
        if (pointCount > 0) {
            return true;
        }
        Long columnCount = photovoltaicPanelColumnService.lambdaQuery()
            .eq(FacPhotovoltaicPanelColumn::getProjectId, projectId)
            .in(FacPhotovoltaicPanelColumn::getMatrixId, matrixIds)
            .count();
        if (columnCount > 0) {
            return true;
        }
        Long supportCount = photovoltaicPanelSupportService.lambdaQuery()
            .eq(FacPhotovoltaicPanelSupport::getProjectId, projectId)
            .in(FacPhotovoltaicPanelSupport::getMatrixId, matrixIds)
            .count();
        return supportCount > 0;
    }

    /**
     * 根据光伏板名称判断是否存在光伏板点
     *
     * @param projectId              项目id
     * @param photovoltaicPanelNames 光伏板名称列表
     * @return 是否存在
     */
    @Override
    public Boolean validPartsExistByPhotovoltaicPanel(Long projectId, Collection<String> photovoltaicPanelNames) {
        LambdaQueryWrapper<FacPhotovoltaicPanelPoint> pointWrapper = new LambdaQueryWrapper<>();
        pointWrapper.and(query -> {
            for (String name : photovoltaicPanelNames) {
                query.or().likeRight(FacPhotovoltaicPanelPoint::getName, name + ".");
            }
        });
        if (photovoltaicPanelPointService.count(pointWrapper) > 0) {
            return true;
        }
        LambdaQueryWrapper<FacPhotovoltaicPanelColumn> ColumnWrapper = new LambdaQueryWrapper<>();
        ColumnWrapper.and(query -> {
            for (String name : photovoltaicPanelNames) {
                query.or().likeRight(FacPhotovoltaicPanelColumn::getName, name + ".");
            }
        });
        if (photovoltaicPanelColumnService.count(ColumnWrapper) > 0) {
            return true;
        }
        LambdaQueryWrapper<FacPhotovoltaicPanelSupport> supportWrapper = new LambdaQueryWrapper<>();
        supportWrapper.and(query -> {
            for (String name : photovoltaicPanelNames) {
                query.or().likeRight(FacPhotovoltaicPanelSupport::getName, name + ".");
            }
        });
        return photovoltaicPanelSupportService.count(supportWrapper) > 0;
    }

    /**
     * 校验名称是否重复
     *
     * @param projectId 项目ID
     * @param name      名称
     */
    private void validName(Long projectId, String name) {
        if (StringUtils.isBlank(name)) {
            throw new ServiceException("桩点、立柱、支架名称不能为空");
        }
        // 参数校验
        Long pointCount = photovoltaicPanelPointService.lambdaQuery()
            .eq(FacPhotovoltaicPanelPoint::getProjectId, projectId)
            .eq(FacPhotovoltaicPanelPoint::getName, name)
            .count();
        if (pointCount > 0) {
            throw new ServiceException("桩点名称重复");
        }
        Long columnCount = photovoltaicPanelColumnService.lambdaQuery()
            .eq(FacPhotovoltaicPanelColumn::getProjectId, projectId)
            .eq(FacPhotovoltaicPanelColumn::getName, name)
            .count();
        if (columnCount > 0) {
            throw new ServiceException("立柱名称重复");
        }
        Long supportCount = photovoltaicPanelSupportService.lambdaQuery()
            .eq(FacPhotovoltaicPanelSupport::getProjectId, projectId)
            .eq(FacPhotovoltaicPanelSupport::getName, name)
            .count();
        if (supportCount > 0) {
            throw new ServiceException("支架名称重复");
        }
    }

}
