/**
 * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
 * <p>
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiaoniu.subsystem.business.controller;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.xiaoniu.common.core.constant.Constants;
import com.xiaoniu.common.core.result.R;
import com.xiaoniu.common.core.utils.BeanUtil;
import com.xiaoniu.common.core.utils.DateUtils;
import com.xiaoniu.common.core.utils.poi.ExcelUtil;
import com.xiaoniu.common.core.utils.poi.SheetPO;
import com.xiaoniu.common.log.annotation.Log;
import com.xiaoniu.common.log.enums.BusinessType;
import com.xiaoniu.subsystem.business.domain.*;
import com.xiaoniu.subsystem.business.domain.dto.*;
import com.xiaoniu.subsystem.business.domain.vo.ProjectExcelVO;
import com.xiaoniu.subsystem.business.domain.vo.ProjectPersonnelInfoExcelVO;
import com.xiaoniu.subsystem.business.domain.vo.ProjectVO;
import com.xiaoniu.subsystem.business.service.*;
import com.xiaoniu.subsystem.system.domain.SysDictData;
import com.xiaoniu.subsystem.system.domain.Unit;
import com.xiaoniu.subsystem.system.domain.vo.SysDictDataVO;
import com.xiaoniu.subsystem.system.service.ISysDictDataService;
import com.xiaoniu.subsystem.system.service.IUnitService;
import com.xiaoniu.subsystem.system.utils.MobileNumberValidator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

import static com.xiaoniu.common.security.utils.SecurityUtils.getUnitId;
import static com.xiaoniu.common.security.utils.SecurityUtils.getUserId;

/**
 * 培训计划管理表 控制器
 *
 * @author sst
 * @since 2024-11-26
 */
@RestController
@AllArgsConstructor
@RequestMapping("/project")
@Tag(name = "培训计划管理表", description = "培训计划管理表接口")
public class ProjectController {

    private final IDemandService demandService;
    private IProjectService projectService;
    private IProjectPersonnelInfoService personnelInfoService;
    private IWaitDoneService waitDoneService;
    private ISysDictDataService dictDataService;
    private IProjectUnitService projectUnitService;
    private IUnitService unitService;


    /**
     * 详情
     */
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @Operation(summary = "详情", description = "传入project")
    public R<ProjectVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long projectId) {
        Project detail = projectService.getById(projectId);
        return R.data(BeanUtil.copy(detail, ProjectVO.class));
    }

    /**
     * 分页 培训计划管理表
     */
    @GetMapping("/page")
    @ApiOperationSupport(order = 2)
    @Operation(summary = "分页", description = "传入project")
    public R<IPage<ProjectVO>> page(@Validated ProjectPageDTO dto) {
        IPage<Project> pages = projectService.page(new Page<>(dto.getPageNum(), dto.getPageSize()),
                new LambdaQueryWrapper<Project>()
                        .orderByDesc(Project::getUpdateTime, Project::getYear, Project::getFlightId, Project::getTrainingTime)
                        .eq(Project::getCreateDept, getUnitId())
                        .like(StringUtils.isNotBlank(dto.getTrainingBatch()), Project::getTrainingBatch, dto.getTrainingBatch())
                        .eq(StringUtils.isNotBlank(dto.getMajorType()), Project::getMajorType, dto.getMajorType())
                        .eq(null != dto.getProjectId(), Project::getProjectId, dto.getProjectId())
                        .eq(null != dto.getStatus(), Project::getStatus, dto.getStatus())
                        .eq(null != dto.getFlightId(), Project::getFlightId, dto.getFlightId())
                        .like(StringUtils.isNotBlank(dto.getFlightName()), Project::getFlightName, dto.getFlightName())
                        .eq(null != dto.getTrainingUnitId(), Project::getTrainingUnitId, dto.getTrainingUnitId())
                        .like(StringUtils.isNotBlank(dto.getTrainingUnitName()), Project::getTrainingUnitName, dto.getTrainingUnitName())
                        .like(StringUtils.isNotBlank(dto.getTrainingSite()), Project::getTrainingSite, dto.getTrainingSite())
                        .like(StringUtils.isNotBlank(dto.getContactPerson()), Project::getContactPerson, dto.getContactPerson())
                        .like(StringUtils.isNotBlank(dto.getPhonenumber()), Project::getPhonenumber, dto.getPhonenumber())
                        .eq(StringUtils.isNotBlank(dto.getYear()), Project::getYear, dto.getYear()));
        return R.data(BeanUtil.copy(pages, ProjectVO.class));
    }

    /**
     * 导出
     */
    @GetMapping("/export")
    @ApiOperationSupport(order = 3)
    @Log(title = "计划导出", businessType = BusinessType.EXPORT)
    @Operation(summary = "导出", description = "传入ids")
    public void export(HttpServletResponse response, @Validated ProjectPageDTO dto) {
        List<Project> list = new ArrayList<>();
        if (StringUtils.isNotBlank(dto.getIds())) {
            list.addAll(projectService.list(new LambdaQueryWrapper<Project>()
                    .orderByDesc(Project::getCreateTime)
                    .in(StringUtils.isNotBlank(dto.getIds()), Project::getProjectId,
                            Arrays.stream(dto.getIds().split(",")).toList())));
        } else {
            list.addAll(projectService.list(new LambdaQueryWrapper<Project>()
                    .orderByDesc(Project::getUpdateTime, Project::getYear, Project::getFlightId, Project::getTrainingTime)
                    .eq(Project::getCreateDept, getUnitId())
                    .like(StringUtils.isNotBlank(dto.getTrainingBatch()), Project::getTrainingBatch, dto.getTrainingBatch())
                    .eq(StringUtils.isNotBlank(dto.getMajorType()), Project::getMajorType, dto.getMajorType())
                    .eq(null != dto.getProjectId(), Project::getProjectId, dto.getProjectId())
                    .eq(null != dto.getStatus(), Project::getStatus, dto.getStatus())
                    .eq(null != dto.getFlightId(), Project::getFlightId, dto.getFlightId())
                    .like(StringUtils.isNotBlank(dto.getFlightName()), Project::getFlightName, dto.getFlightName())
                    .eq(null != dto.getTrainingUnitId(), Project::getTrainingUnitId, dto.getTrainingUnitId())
                    .like(StringUtils.isNotBlank(dto.getTrainingUnitName()), Project::getTrainingUnitName, dto.getTrainingUnitName())
                    .like(StringUtils.isNotBlank(dto.getTrainingSite()), Project::getTrainingSite, dto.getTrainingSite())
                    .like(StringUtils.isNotBlank(dto.getContactPerson()), Project::getContactPerson, dto.getContactPerson())
                    .like(StringUtils.isNotBlank(dto.getPhonenumber()), Project::getPhonenumber, dto.getPhonenumber())
                    .eq(StringUtils.isNotBlank(dto.getYear()), Project::getYear, dto.getYear())));
        }
        List<ProjectExcelVO> list1 = new ArrayList<ProjectExcelVO>();
        List<ProjectPersonnelInfoExcelVO> list2 = new ArrayList<ProjectPersonnelInfoExcelVO>();
        if (CollectionUtils.isNotEmpty(list)) {
            List<SysDictData> data = dictDataService.list(
                    new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, "1"));
            Map<String, String> map = data.stream()
                    .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
            List<SysDictData> data1 = dictDataService.list(
                    new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, "2"));
            Map<String, String> map1 = data1.stream()
                    .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
            for (Project project : list) {
                list1.add(BeanUtil.copy(project, ProjectExcelVO.class)
                        .setTrainingTypeNane(Arrays.stream(project.getTrainingType()
                                .split(",")).map(map1::get).collect(Collectors.joining(",")))
                        .setMajorTypeName(map.get(project.getMajorType())));
                List<Long> longs = new ArrayList<Long>();
                longs.add(project.getProjectId());
                List<Project> projects = projectService.list(new LambdaQueryWrapper<Project>()
                        .eq(Project::getParentId, project.getProjectId()));
                getLongList(projects, longs);
                List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                        .eq(Unit::getParentId, getUnitId()));
                List<ProjectPersonnelInfo> list3 =
                        personnelInfoService.list(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                                .eq(CollectionUtils.isNotEmpty(units), ProjectPersonnelInfo::getIsReport, "1")
                                .in(CollectionUtils.isNotEmpty(longs), ProjectPersonnelInfo::getProjectId, longs));
                if (CollectionUtils.isNotEmpty(list3)) {
                    list2.addAll(list3.stream().map(l ->
                            BeanUtil.copy(l, ProjectPersonnelInfoExcelVO.class)
                                    .setMajorTypeName(map.get(l.getMajorType()))
                    ).collect(Collectors.toList()));
                }
            }
        }
        List<SheetPO> sheet = new ArrayList<>();
        sheet.add(new SheetPO().setSheetNo(0).setSheetName("计划数据")
                .setData(list1).setClazz(ProjectExcelVO.class));
        sheet.add(new SheetPO().setSheetNo(1).setSheetName("人员数据")
                .setData(list2).setClazz(ProjectPersonnelInfoExcelVO.class));
        ExcelUtil<List<SheetPO>> excelUtil = new ExcelUtil<>(sheet);
        excelUtil.exportExcelMore(response, sheet);
    }

    /**
     * 新增 培训计划管理表
     */
    @PostMapping("/save")
    @Transactional
    @ApiOperationSupport(order = 4)
    @Operation(summary = "新增", description = "传入project")
    public R save(@Valid @RequestBody ProjectSaveDTO project) {
        for (String s : Arrays.stream(project.getPhonenumber().split(",")).toList()) {
            if (!MobileNumberValidator.isValidPhoneNumber(s)){
                return R.fail("电话号码有误：" + s +"，请核对");
            }
        }
        Project one = projectService.getOne(new LambdaQueryWrapper<Project>()
                .eq(Project::getFlightName, project.getFlightName())
                // .eq(Project::getTrainingBatch, project.getTrainingBatch())
                .eq(Project::getTrainingTime, project.getTrainingTime())
                .eq(Project::getParentId, 0)
                .eq(Project::getYear, project.getYear()));
        if (null != one) {
            return R.fail("已存在年度：" + project.getYear() +
                    "度,开训时间：" + DateUtils.dateTime(project.getTrainingTime()) +
                    ",专业（班次）名称：" + project.getFlightName() + "的计划，请核对");
        }
        Project copy = BeanUtil.copy(project, Project.class)
                .setCreateDept(getUnitId())
                .setCreateUser(getUserId()).setCreateTime(new Date())
                .setShouldAttendance(project.getTrainingPost());
        projectService.save(copy);
        List<Project> list = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(Project::getFlightId, copy.getFlightId()));
        if(CollectionUtils.isNotEmpty(list) && list.size() > 1) {
            projectService.updateBatchById(list.stream().peek( l ->
                    l.setUpdateTime(new Date())).collect(Collectors.toList()));
        }
        return R.status(projectUnitService.saveBatch(
                BeanUtil.copy(project.getProjectUnitDTOS(), ProjectUnit.class)
                        .stream().peek(p -> p.setProjectId(copy.getProjectId())
                                .setCreateDept(getUnitId())
                                .setCreateUser(getUserId())
                                .setCreateTime(new Date())
                        ).collect(Collectors.toList())));
    }

    /**
     * 修改 培训计划管理表
     */
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @Operation(summary = "修改", description = "传入project")
    public R update(@Valid @RequestBody ProjectUpdateDTO dto) {
        for (String s : Arrays.stream(dto.getPhonenumber().split(",")).toList()) {
            if (!MobileNumberValidator.isValidPhoneNumber(s)){
                return R.fail("电话号码有误：" + s +"，请核对");
            }
        }
        boolean b = projectService.updateById(BeanUtil.copy(dto, Project.class)
                .setUpdateUser(getUserId()).setUpdateTime(new Date()));
        List<Project> list2 = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(Project::getFlightId, dto.getFlightId()));
        if(CollectionUtils.isNotEmpty(list2) && list2.size() > 1) {
            projectService.updateBatchById(list2.stream().peek( l ->
                    l.setUpdateTime(new Date())).collect(Collectors.toList()));
        }
        projectUnitService.saveOrUpdateBatch(BeanUtil.copy(dto.getProjectUnitDTOS(), ProjectUnit.class)
                .stream().peek(p -> p.setProjectId(dto.getProjectId())
                        .setUpdateTime(new Date())
                        .setUpdateUser(getUserId())
                ).collect(Collectors.toList()));
        return R.status(b);
    }

    /**
     * 获取需求报名人数
     */
    @GetMapping("/get/flightIds")
    @ApiOperationSupport(order = 13)
    @Operation(summary = "获取协议/合同班次ids")
    public R<List<Long>> getPeopleNum() {
        List<Project> list = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(Project::getCreateDept,getUnitId()));
        if (CollectionUtils.isEmpty(list)) return R.data(Collections.emptyList());
        return R.data(list.stream().map(Project::getFlightId).toList());
    }
    /**
     * 修改 培训计划状态修改
     */
    @PostMapping("/update/data/state")
    @ApiOperationSupport(order = 6)
    @Operation(summary = "培训计划状态修改", description = "传入project")
    public R updateDataState(@Valid @RequestBody ProjectDistributionDTO dto) {
        Project project = projectService.getById(dto.getProjectId());
        List<Project> list2 = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(Project::getFlightId, project.getFlightId()));
        if(CollectionUtils.isNotEmpty(list2) && list2.size() > 1) {
            projectService.updateBatchById(list2.stream().peek( l ->
                    l.setUpdateTime(new Date())).collect(Collectors.toList()));
        }
        if (1 == dto.getIsDistribution()) {
            return R.status(distribution(dto, project));
        }
        List<Project> result = new ArrayList<Project>();
        result.add(project);
        List<Project> list = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(Project::getParentId, dto.getProjectId()));
        if (CollectionUtils.isNotEmpty(list)) {
            result.addAll(list);
            List<Project> list1 = projectService.list(new LambdaQueryWrapper<Project>()
                    .in(Project::getParentId, list.stream()
                            .map(Project::getProjectId).collect(Collectors.toList())));
            if (CollectionUtils.isNotEmpty(list1)) {
                result.addAll(list1);
                getProjects(list1, result);
            }
        }
        List<Long> longs = result.stream().map(Project::getProjectId).collect(Collectors.toList());
        projectUnitService.update(new LambdaUpdateWrapper<ProjectUnit>()
                .set(ProjectUnit::getIsDeleted, 1)
                .in(ProjectUnit::getProjectId, longs));
        personnelInfoService.update(new LambdaUpdateWrapper<ProjectPersonnelInfo>()
                .set(ProjectPersonnelInfo::getIsDeleted, 1)
                .in(ProjectPersonnelInfo::getProjectId, longs));

        return R.status(projectService.updateBatchById(
                result.stream().peek(l ->
                        l.setIsDistribution(dto.getIsDistribution())
                                .setUpdateUser(getUserId())
                                .setUpdateTime(new Date())
                ).collect(Collectors.toList())));
    }

    /**
     * 删除 培训计划管理表
     */
    @PostMapping("/remove")
    @ApiOperationSupport(order = 7)
    @Operation(summary = "删除", description = "传入ids")
    public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String projectIds) {
        List<Long> longs = Arrays.stream(projectIds.split(",")).map(Long::parseLong).toList();
        List<Project> list = projectService.listByIds(longs);
        List<Project> collect = list.stream().filter(l ->
                4 != l.getIsDistribution() && 0 != l.getIsDistribution()).toList();
        if (CollectionUtils.isNotEmpty(collect)) {
            return R.fail("存在已下发或已完成计划，无法删除，请作废后操作");
        }
        List<Project> list1 = projectService.list(new LambdaQueryWrapper<Project>().in(Project::getParentId, longs));
        if (CollectionUtils.isNotEmpty(list1)) {
            projectService.removeByIds(list1.stream().map(Project::getProjectId).collect(Collectors.toList()));
            projectUnitService.remove(new LambdaQueryWrapper<ProjectUnit>()
                    .in(ProjectUnit::getProjectId, list1.stream().map(Project::getProjectId).collect(Collectors.toList())));
            personnelInfoService.remove(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                    .in(ProjectPersonnelInfo::getProjectId, list1.stream().map(Project::getProjectId).collect(Collectors.toList())));
            deleteBatch(list1);
        }
        projectUnitService.remove(new LambdaQueryWrapper<ProjectUnit>().in(ProjectUnit::getProjectId, longs));
        personnelInfoService.remove(new LambdaQueryWrapper<ProjectPersonnelInfo>().in(ProjectPersonnelInfo::getProjectId, longs));
        return R.status(projectService.removeByIds(longs));
    }

    /**
     * 获取字典
     */
    @GetMapping("/dictionary")
    @ApiOperationSupport(order = 9)
    @Operation(summary = "获取字典", description = "传入project")
    public R<List<SysDictDataVO>> dictionary(@Parameter(description = "字典数据类型(1-专业类型)", required = true) @RequestParam String type) {
        SysDictData data = new SysDictData();
        data.setDictType(type);
        List<SysDictData> list = dictDataService.selectDictDataList(data);
        return R.data(BeanUtil.copy(list, SysDictDataVO.class));
    }

    /**
     * 上传文件回调修改
     */
    @PostMapping("/update/upload")
    @ApiOperationSupport(order = 12)
    @Operation(summary = "上传文件回调修改", description = "传入demand")
    public R updateUpload(@Valid @RequestBody ProjectUpdateNewDTO dto) {
        projectService.updateById(BeanUtil.copy(dto, Project.class)
                .setUpdateUser(getUserId()).setUpdateTime(new Date()));
        List<Project> list1 = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(Project::getParentId, dto.getProjectId()));
        if (CollectionUtils.isNotEmpty(list1)) {
            projectService.updateBatchById(list1.stream().peek(l -> {
                if (StringUtils.isNotBlank(dto.getIntroUrl())) {
                    l.setIntroUrl(dto.getIntroUrl());
                }
                if (StringUtils.isNotBlank(dto.getOptionUrl())) {
                    l.setOptionUrl(dto.getOptionUrl());
                }
                l.setUpdateUser(getUserId()).setUpdateTime(new Date());
            }).collect(Collectors.toList()));
            updateBatch(list1, dto);
        }
        Project byId = projectService.getById(dto.getProjectId());
        List<Project> list2 = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(Project::getFlightId, byId.getFlightId()));
        if(CollectionUtils.isNotEmpty(list2) && list2.size() > 1) {
            projectService.updateBatchById(list2.stream().peek( l ->
                    l.setUpdateTime(new Date())).collect(Collectors.toList()));
        }
        List<Demand> list = demandService.list(new LambdaQueryWrapper<Demand>()
                .eq(Demand::getFlightId, byId.getFlightId()));
        if (CollectionUtils.isNotEmpty(list)) {
            demandService.updateBatchById(list.stream().peek(l -> {
                if (StringUtils.isNotBlank(dto.getIntroUrl())) {
                    l.setIntroUrl(dto.getIntroUrl());
                }
                if (StringUtils.isNotBlank(dto.getOptionUrl())) {
                    l.setOptionUrl(dto.getOptionUrl());
                }
                l.setUpdateUser(getUserId()).setUpdateTime(new Date());
            }).collect(Collectors.toList()));
        }
        return R.status(true);
    }


    public boolean distribution(ProjectDistributionDTO dto, Project project) {
        List<ProjectUnit> list = projectUnitService.list(new LambdaQueryWrapper<ProjectUnit>()
                .eq(ProjectUnit::getProjectId, dto.getProjectId()));
        if (CollectionUtils.isEmpty(list)) {
            throw new SecurityException("没有查询到需要下发的单位信息，请编辑下级单位");
        }
        List<ProjectUnit> unitList = list.stream().filter(l -> 0 != l.getPeopleNum()).toList();
        if (CollectionUtils.isEmpty(unitList)) {
            throw new SecurityException("下发的单位信息没有人员数量，请编辑下级单位");
        }
        for (ProjectUnit unit : unitList) {
            List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                    .eq(Unit::getParentId, unit.getUnitId()));
            Project attendance = BeanUtil.copy(project, Project.class)
                    .setProjectId(null)
                    .setIsDistribution(CollectionUtils.isEmpty(units) ? 1 : 0)
                    .setCreateTime(new Date())
                    .setParentId(project.getProjectId())
                    .setCreateDept(unit.getUnitId())
                    .setShouldAttendance(unit.getPeopleNum().toString());
            projectService.save(attendance);
            waitDoneService.save(new WaitDone()
                    .setBusinessId(attendance.getProjectId())
                    .setWaitDoneUnit(unit.getUnitId())
                    .setWaitDoneMessage("计划下发待办提示,点击查看详情")
                    .setType("2")
                    .setStatus(Constants.ZERO)
                    .setFlightId(attendance.getFlightId())
                    .setFlightName(attendance.getFlightName())
                    .setSkip("")
                    .setCreateDept(getUnitId()));
        }
        return projectService.updateById(project.setIsDistribution(dto.getIsDistribution()));
    }


    private void getProjects(List<Project> list, List<Project> result) {
        List<Project> list1 = projectService.list(new LambdaQueryWrapper<Project>()
                .in(Project::getParentId, list.stream().map(Project::getProjectId).collect(Collectors.toList())));
        if (CollectionUtils.isNotEmpty(list1)) {
            result.addAll(list1);
            getProjects(list1, result);
        }
    }

    private void updateBatch(List<Project> list, ProjectUpdateNewDTO dto) {
        List<Project> list1 = projectService.list(new LambdaQueryWrapper<Project>()
                .in(Project::getParentId,
                        list.stream().map(Project::getProjectId).collect(Collectors.toList())));
        if (CollectionUtils.isNotEmpty(list1)) {
            projectService.updateBatchById(list1.stream().peek(l ->
                    l.setIntroUrl(dto.getIntroUrl()).setOptionUrl(dto.getOptionUrl())
                            .setUpdateUser(getUserId()).setUpdateTime(new Date())
            ).collect(Collectors.toList()));
            updateBatch(list1, dto);
        }
    }

    private void getLongList(List<Project> list, List<Long> longs) {
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> longList = list.stream().map(Project::getProjectId).toList();
            longs.addAll(longList);
            List<Project> projectList = projectService.list(new LambdaQueryWrapper<Project>()
                    .in(Project::getParentId, longList));
            getLongList(projectList, longs);
        }
    }

    private void deleteBatch(List<Project> list) {
        List<Project> list1 = projectService.list(new LambdaQueryWrapper<Project>()
                .in(Project::getParentId,
                        list.stream().map(Project::getProjectId).collect(Collectors.toList())));
        if (CollectionUtils.isNotEmpty(list1)) {
            projectService.removeByIds(list1.stream().map(Project::getProjectId).collect(Collectors.toList()));
            projectUnitService.remove(new LambdaQueryWrapper<ProjectUnit>()
                    .in(ProjectUnit::getProjectId, list1.stream().map(Project::getProjectId).collect(Collectors.toList())));
            personnelInfoService.remove(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                    .in(ProjectPersonnelInfo::getProjectId, list1.stream().map(Project::getProjectId).collect(Collectors.toList())));
            deleteBatch(list1);
        }
    }
}
