/**
 * 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.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.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.*;
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.service.ISysDictDataService;
import com.xiaoniu.subsystem.system.service.IUnitService;
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 jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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 org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.xiaoniu.common.security.utils.SecurityUtils.*;

/**
 * 培训需求管理表 控制器
 *
 * @author sst
 * @since 2024-11-26
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/demand")
@Tag(name = "培训需求管理", description = "培训需求管理接口")
public class DemandController {

    private final IDemandService demandService;
    private final IDemandSignUpService demandSignUpService;
    private final IWaitDoneService waitDoneService;
    private final IUnitService unitService;
    private final IFlightService flightService;
    private final IDemandTotalService demandTotalService;
    private final IProjectService projectService;
    private ISysDictDataService dictDataService;
    private IProfileManageService profileManageService;


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

    /**
     * 分页 培训需求管理表
     */
    @GetMapping("/page")
    @ApiOperationSupport(order = 2)
    @Operation(summary = "分页", description = "传入demand")
    public R<IPage<DemandPageVO>> page(@Validated DemandPageDTO dto) {
        IPage<Demand> pages = demandService.page(new Page<>(dto.getPageNum(), dto.getPageSize()), set(dto));
        IPage<DemandPageVO> copy = BeanUtil.copy(pages, DemandPageVO.class);
        if (CollectionUtils.isEmpty(pages.getRecords())) {
            return R.data(copy);
        }
        List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getParentId, getUnitId()));
        if (CollectionUtils.isNotEmpty(units)) {
            setPage(copy, units);
        }
        return R.data(copy);

    }


    /**
     * 导出
     */
    @GetMapping("/export")
    @ApiOperationSupport(order = 3)
    @Log(title = "导出", businessType = BusinessType.EXPORT)
    @Operation(summary = "导出", description = "传入ids")
    public void export(HttpServletResponse response, @Validated DemandPageDTO dto) {
        List<Demand> list = new ArrayList<>();
        if (StringUtils.isNotBlank(dto.getIds())) {
            list.addAll(demandService.list(new LambdaQueryWrapper<Demand>()
                    .orderByDesc(Demand::getCreateTime)
                    .eq(Demand::getType, dto.getType())
                    .in(StringUtils.isNotBlank(dto.getIds()), Demand::getDemandId,
                            Arrays.stream(dto.getIds().split(",")).toList())));
        } else {
            list.addAll(demandService.list(set(dto)));
        }
        List<DemandExcelVO> list1 = new ArrayList<>();
        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 (Demand demand : list) {
                list1.add(BeanUtil.copy(demand, DemandExcelVO.class)
                        .setTrainingTypeNane(Arrays.stream(demand.getTrainingType()
                                .split(",")).map(map1::get).collect(Collectors.joining(",")))
                        .setMajorTypeName(map.get(demand.getMajorType())));
            }
        }
        ExcelUtil<DemandExcelVO> excelUtil = new ExcelUtil<>(DemandExcelVO.class);
        excelUtil.exportExcel(response, list1, "需求数据");
    }

    /**
     * 新增 培训需求管理表
     */
    @PostMapping("/save")
    @Transactional
    @ApiOperationSupport(order = 4)
    @Operation(summary = "新增", description = "传入demand")
    public R save(@Valid @RequestBody DemandSaveDTO dto) {
        if (StringUtils.equals("admin", getUsername()) || 0 == getUnitId()) {
            return R.fail("只有机关单位的账号可以新增，超级管理员只有设置权限，请更换账号");
        }
        Unit unit = unitService.getById(getUnitId());
        Demand copy = BeanUtil.copy(dto, Demand.class)
                .setCreateDept(unit.getUnitId())
                .setCreateUser(getUserId())
                .setCreateTime(new Date());
        Demand one = demandService.getOne(new LambdaQueryWrapper<Demand>()
                .eq(Demand::getFlightName, copy.getFlightName())
                //.eq(Demand::getTrainingBatch, copy.getTrainingBatch())
                .eq(Demand::getTrainingTime, copy.getTrainingTime())
                .eq(Demand::getParentId, 0)
                .eq(Demand::getYear, copy.getYear())
                .last("limit 1")
        );
        if (null != one) {
            return R.fail("已存在年度：" + dto.getYear() +
                    "度,开训时间：" + DateUtils.dateTime(dto.getTrainingTime()) +
                    ",专业（班次）名称：" + dto.getFlightName() +
                    "的需求，请核对");
        }
        demandService.save(copy);
        Flight flight = flightService.getOne(new LambdaQueryWrapper<Flight>()
                .eq(Flight::getFlightName, copy.getFlightName())
                .eq(Flight::getTrainingTime,copy.getTrainingTime())
                .eq(Flight::getYear, copy.getYear()));
        if (null != flight) {
            copy.setFlightId(flight.getFlightId()).setFlightCode(flight.getFlightCode());
            List<Demand> list = demandService.list(new LambdaQueryWrapper<Demand>()
                    .eq(Demand::getFlightName, copy.getFlightName())
                    .eq(Demand::getTrainingTime,copy.getTrainingTime())
                    .eq(Demand::getYear, copy.getYear()));
            if (CollectionUtils.isNotEmpty(list)) {
                demandService.updateBatchById(list.stream().peek(l ->
                        l.setUpdateUser(getUserId()).setUpdateTime(new Date())
                ).collect(Collectors.toList()));
            }
        } else {
            Flight flight1 = new Flight()
                    .setFlightName(copy.getFlightName())
                    .setFlightCode("ZY" + LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli())
                    .setEducationalSystem(copy.getEducationalSystem())
                    .setTrainingTime(copy.getTrainingTime())
                    .setYear(copy.getYear())
                    .setType(copy.getTrainingType())
                    .setMajorType(copy.getMajorType())
                    .setTrainingPost(copy.getTraineesMumber())
                    .setTissueUnitId(copy.getTrainingUnitId())
                    .setTissueUnitName(copy.getTrainingUnitName())
                    .setTissueUnitAddress(copy.getTrainingSite())
                    .setContactPerson(copy.getContactPerson())
                    .setPhonenumber(copy.getPhonenumber())
                    .setMainUnitId(copy.getMainUnitId())
                    .setMainUnitName(copy.getMainUnitName())
                    .setCreateDept(unit.getUnitId())
                    .setCreateUser(getUserId())
                    .setCreateTime(new Date());
            flightService.save(flight1);
            copy.setFlightId(flight1.getFlightId()).setFlightCode(flight1.getFlightCode());
            //创建班次关联文件资料数据
            //评审资料
            SysDictData data = new SysDictData();
            data.setDictType("4");
            List<SysDictData> list = dictDataService.selectDictDataList(data);
            for (SysDictData sys : list) {
                ProfileManage profileManage = new ProfileManage();
                profileManage.setProfileName(sys.getDictValue());
                profileManage.setType("2");
                profileManage.setFlightId(flight1.getFlightId());
                profileManage.setFlightName(flight1.getFlightName());
                profileManage.setFlightCode(flight1.getFlightCode());
                profileManage.setSuperintendent(flight1.getContactPerson());
                profileManage.setYear(String.valueOf(LocalDate.now().getYear()))
                        .setCreateDept(getUnitId())
                        .setCreateUser(getUserId())
                        .setCreateTime(new Date());
                profileManageService.save(profileManage);
            }
            //结业资料
            data.setDictType("5");
            List<SysDictData> list1 = dictDataService.selectDictDataList(data);
            for (SysDictData sys : list1) {
                ProfileManage profileManage = new ProfileManage();
                profileManage.setProfileName(sys.getDictValue());
                profileManage.setType("0");
                profileManage.setFlightId(flight1.getFlightId());
                profileManage.setFlightName(flight1.getFlightName());
                profileManage.setFlightCode(flight1.getFlightCode());
                profileManage.setSuperintendent(flight1.getContactPerson());
                profileManage.setYear(String.valueOf(LocalDate.now().getYear()))
                        .setCreateDept(getUnitId())
                        .setCreateUser(getUserId())
                        .setCreateTime(new Date());
                profileManageService.save(profileManage);

            }
            //结算资料
            data.setDictType("6");
            List<SysDictData> list2 = dictDataService.selectDictDataList(data);
            for (SysDictData sys : list2) {
                ProfileManage profileManage = new ProfileManage();
                profileManage.setProfileName(sys.getDictValue());
                profileManage.setType("1");
                profileManage.setFlightId(flight1.getFlightId());
                profileManage.setFlightName(flight1.getFlightName());
                profileManage.setFlightCode(flight1.getFlightCode());
                profileManage.setSuperintendent(flight1.getContactPerson());
                profileManage.setYear(String.valueOf(LocalDate.now().getYear()))
                        .setCreateDept(getUnitId())
                        .setCreateUser(getUserId())
                        .setCreateTime(new Date());
                profileManageService.save(profileManage);
            }
        }
        return R.status(demandService.updateById(copy));
    }

    /**
     * 修改 培训需求管理表
     */
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @Operation(summary = "修改", description = "传入demand")
    public R update(@Valid @RequestBody DemandUpdateDTO dto) {
        Demand one = demandService.getOne(new LambdaQueryWrapper<Demand>()
                .ne(Demand::getDemandId, dto.getDemandId())
                .eq(Demand::getFlightName, dto.getFlightName())
                //.eq(Demand::getTrainingBatch, dto.getTrainingBatch())
                .eq(Demand::getTrainingTime, dto.getTrainingTime())
                .eq(Demand::getParentId, 0)
                .eq(Demand::getYear, dto.getYear()));
        if (null != one) {
            return R.fail("已存在年度：" + dto.getYear() +
                    "年度,开训时间：" + DateUtils.dateTime(dto.getTrainingTime()) +
                    ",专业（班次）名称：" + dto.getFlightName() + "的需求，请核对");
        }
        Demand byId = demandService.getById(dto.getDemandId());
        if (null != byId) {
            Demand copy = BeanUtil.copy(dto, Demand.class)
                    .setUpdateUser(getUserId()).setUpdateTime(new Date());
            Flight flight = flightService.getOne(new LambdaQueryWrapper<Flight>()
                    .eq(Flight::getFlightName, copy.getFlightName())
                    .eq(Flight::getTrainingTime, copy.getTrainingTime())
                    .eq(Flight::getYear, copy.getYear()));
            if (null != flight) {
                copy.setFlightId(flight.getFlightId());
                flight.setMajorType(copy.getMajorType());
                flightService.updateById(flight);
            }
            if (StringUtils.equals("0", dto.getIsIssue()) && !StringUtils.equals("0", byId.getIsIssue())) {
                copy.setIsIssue(byId.getIsIssue());
            }
            demandService.updateById(copy);
            if (StringUtils.equals("0", dto.getIsIssue()) && StringUtils.equals("0", byId.getIsIssue())) {
                return R.status(true);
            }
            if (StringUtils.equals("1", dto.getIsIssue()) && StringUtils.equals("0", byId.getIsIssue())) {
                if (StringUtils.isNotBlank(dto.getUnitIds())) {
                    Stream.of(dto.getUnitIds().split(",")).forEach(d -> saveBatch(Long.valueOf(d), copy));
                } else {
                    List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                            .eq(Unit::getParentId, getUnitId()));
                    if (CollectionUtils.isNotEmpty(units)) {
                        units.forEach(d -> saveBatch(d.getUnitId(), copy));
                    }
                }
            } else {
                List<Demand> list = demandService.list(new LambdaQueryWrapper<Demand>()
                        .eq(Demand::getParentId, copy.getDemandId()));
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(l -> updateBatch(l
                            .setFlightId(copy.getFlightId()).setIsIssue(dto.getIsIssue())));
                }
            }
        }
        return R.status(true);
    }

    /**
     * 删除 培训需求管理表
     */
    @PostMapping("/remove")
    @ApiOperationSupport(order = 7)
    @Operation(summary = "删除", description = "传入ids")
    public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String demandIds) {
        List<Long> longs = Arrays.stream(demandIds.split(",")).map(Long::parseLong).toList();
/*        List<Demand> list = demandService.listByIds(longs);
        List<Demand> collect = list.stream().filter(l -> !StringUtils.equals("3", l.getIsIssue())
                && !StringUtils.equals("0", l.getIsIssue())).toList();
        if (CollectionUtils.isNotEmpty(collect)) {
            return R.fail("存在已下发或已完成需求，无法删除，请作废后操作");
        }*/
        List<Demand> list1 = demandService.list(new LambdaQueryWrapper<Demand>().in(Demand::getParentId, longs));
        if (CollectionUtils.isNotEmpty(list1)) {
            demandService.removeByIds(list1.stream().map(Demand::getDemandId).collect(Collectors.toList()));
            demandTotalService.remove(new LambdaQueryWrapper<DemandTotal>()
                    .in(DemandTotal::getDemandId, list1.stream().map(Demand::getDemandId).collect(Collectors.toList())));
            demandSignUpService.remove(new LambdaQueryWrapper<DemandSignUp>()
                    .in(DemandSignUp::getDemandId, list1.stream().map(Demand::getDemandId).collect(Collectors.toList())));
            deleteBatch(list1);
        }
        demandTotalService.remove(new LambdaQueryWrapper<DemandTotal>().in(DemandTotal::getDemandId, longs));
        demandSignUpService.remove(new LambdaQueryWrapper<DemandSignUp>().in(DemandSignUp::getDemandId, longs));
        return R.status(demandService.removeByIds(longs));
    }


    @PostMapping("/import")
    @ApiOperationSupport(order = 9)
    @Log(title = "培训需求导入", businessType = BusinessType.IMPORT)
    @Operation(summary = "导入")
    public R importData(MultipartFile file,
                        @Parameter(description = "是否支持更新", required = true)
                        @RequestParam boolean updateSupport,
                        @RequestParam Integer type) throws Exception {
        if (StringUtils.equals("admin", getUsername()) || 0 == getUnitId()) {
            return R.fail("只有承训单位的账号可以新增，超级管理员只有设置权限，请更换账号");
        }
        ExcelUtil<DemandExcelDTO> util = new ExcelUtil<>(DemandExcelDTO.class);
        List<DemandExcelDTO> list = util.importExcel(file.getInputStream());
        List<Demand> list1 = new ArrayList<>();
        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::getDictValue, SysDictData::getDictLabel));
            List<SysDictData> data1 = dictDataService.list(
                    new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, "2"));
            Map<String, String> map1 = data1.stream()
                    .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
            for (DemandExcelDTO demand : list) {
                list1.add(BeanUtil.copy(demand, Demand.class)
                        .setTrainingType(Arrays.stream(demand.getTrainingTypeNane()
                                .split(",")).map(map1::get).collect(Collectors.joining(",")))
                        .setMajorType(map.get(demand.getMajorTypeName())));
            }
        }
        return R.success(demandService.importData(list1, updateSupport, type));
    }

    @GetMapping("/importTemplate")
    @ApiOperationSupport(order = 10)
    @Operation(summary = "导入模版下载")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<Demand> util = new ExcelUtil<>(Demand.class);
        util.importTemplateExcel(response, "培训需求导入模版");
    }

    /**
     * 审核列表
     */
    @GetMapping("/audit/list")
    @ApiOperationSupport(order = 11)
    @Operation(summary = "审核列表", description = "传入demand")
    public R<DemandAuditVO> auditList(@Parameter(description = "主键", required = true)
                                      @NotNull(message = "需求主键不能为空")
                                      @RequestParam Long demandId) {
        List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getParentId, getUnitId()));
        Demand byId = demandService.getById(demandId);
        DemandAuditVO copy = BeanUtil.copy(byId, DemandAuditVO.class);
        if (CollectionUtils.isNotEmpty(units)) {
            List<Demand> list1 = demandService.list(new LambdaQueryWrapper<Demand>()
                    .in(Demand::getParentId, demandId));
            if (CollectionUtils.isNotEmpty(list1)) {
                List<DemandTotal> list = demandTotalService.list(new LambdaQueryWrapper<DemandTotal>()
                        .in(DemandTotal::getDemandId,
                                list1.stream().map(Demand::getDemandId).toList()));
                if (CollectionUtils.isEmpty(list)) {
                    Map<Long, Unit> unitMap = units.stream().collect(Collectors.toMap(Unit::getUnitId, e -> e));
                    List<DemandTotalVO> demandTotalVOS = new ArrayList<DemandTotalVO>();
                    list1.forEach(d -> {
                        Unit unit = unitMap.get(d.getCreateDept());
                        DemandTotal totalVO = new DemandTotal()
                                .setDemandId(d.getDemandId())
                                .setUnitId(unit.getUnitId())
                                .setUnitName(unit.getUnitName())
                                .setContactPerson(unit.getContactPerson())
                                .setPhone(unit.getPhone());
                        List<Demand> demandList = new ArrayList<Demand>();
                        demandList.add(d);
                        List<Demand> list2 = demandService.getList(demandList);
                        List<Demand> collect = list2.stream().filter(l -> StringUtils.equals("1",
                                l.getIsReport())).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(collect)) {
                            List<DemandSignUp> list3 = demandSignUpService.list(new LambdaQueryWrapper<DemandSignUp>()
                                    .in(DemandSignUp::getDemandId, collect.stream().map(Demand::getDemandId).toList()));
                            totalVO.setPeopleNum(list3.stream().mapToInt(l ->
                                    Integer.parseInt(l.getForecastAttendance())).sum());
                            demandTotalService.save(totalVO);
                        }
                        demandTotalVOS.add(BeanUtil.copy(totalVO, DemandTotalVO.class));
                    });
                    copy.setDemandTotalVOS(BeanUtil.copy(list, DemandTotalVO.class));
                } else {
                    copy.setDemandTotalVOS(BeanUtil.copy(list, DemandTotalVO.class));
                }
            }
        }
        return R.data(copy);
    }

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

    /**
     * 获取需求报名人数
     */
    @GetMapping("/get/people/num")
    @ApiOperationSupport(order = 13)
    @Operation(summary = "获取需求报名人数", description = "传入demand")
    public R<List<ProjectUnitVO>> getPeopleNum(@Validated DemandSumDTO dto) {
        List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getParentId, getUnitId()));
        Demand demand = demandService.getById(dto.getDemandId());
        return R.data(demandService.getPeopleNum(demand, units));
    }


    private LambdaQueryWrapper<Demand> set(DemandPageDTO dto) {
        return new LambdaQueryWrapper<Demand>()
                .orderByDesc(Demand::getUpdateTime, Demand::getYear, Demand::getFlightId, Demand::getTrainingTime)
                .eq(Demand::getCreateDept, getUnitId())
                .eq(dto.getType() != null, Demand::getType, dto.getType())
                .eq(null != dto.getDemandId(), Demand::getDemandId, dto.getDemandId())
                .eq(null != dto.getFlightId(), Demand::getFlightId, dto.getFlightId())
                .like(StringUtils.isNotBlank(dto.getFlightName()), Demand::getFlightName, dto.getFlightName())
                .eq(StringUtils.isNotBlank(dto.getIsIssue()), Demand::getIsIssue, dto.getIsIssue())
                .like(StringUtils.isNotBlank(dto.getTrainingBatch()), Demand::getTrainingBatch, dto.getTrainingBatch())
                .eq(null != dto.getTrainingUnitId(), Demand::getTrainingUnitId, dto.getTrainingUnitId())
                .eq(null == dto.getTrainingUnitId(),Demand::getTrainingUnitId, getUnitId())
                .like(StringUtils.isNotBlank(dto.getTrainingUnitName()), Demand::getTrainingUnitName, dto.getTrainingUnitName())
                 .eq(null != dto.getMainUnitId(), Demand::getMainUnitId, dto.getMainUnitId())
                 .like(StringUtils.isNotBlank(dto.getMainUnitName()), Demand::getMainUnitName,
                         dto.getMainUnitName())
                .like(StringUtils.isNotBlank(dto.getTrainingType()), Demand::getTrainingType, dto.getTrainingType())
                .like(StringUtils.isNotBlank(dto.getTrainingSite()), Demand::getTrainingSite, dto.getTrainingSite())
                .eq(StringUtils.isNotBlank(dto.getMajorType()), Demand::getMajorType, dto.getMajorType())
                .eq(StringUtils.isNotBlank(dto.getYear()), Demand::getYear, dto.getYear())
                .ge(null != dto.getTrainingTimeStar(), Demand::getTrainingTime,
                        dto.getTrainingTimeStar())
                .le(null != dto.getTrainingTimeEnd(), Demand::getTrainingTime,
                        dto.getTrainingTimeEnd())
                .ge(StringUtils.isNotBlank(dto.getEducationalSystemMin()), Demand::getEducationalSystem,
                        dto.getEducationalSystemMin())
                .le(StringUtils.isNotBlank(dto.getEducationalSystemMax()), Demand::getEducationalSystem,
                        dto.getEducationalSystemMax())
                .ge(StringUtils.isNotBlank(dto.getTraineesMumberMin()), Demand::getTraineesMumber,
                        dto.getTraineesMumberMin())
                .le(StringUtils.isNotBlank(dto.getTraineesMumberMax()), Demand::getTraineesMumber,
                        dto.getTraineesMumberMax())
                .ge(StringUtils.isNotBlank(dto.getMaxTraineesMumberMin()), Demand::getMaxTraineesMumber,
                        dto.getMaxTraineesMumberMin())
                .le(StringUtils.isNotBlank(dto.getMaxTraineesMumberMax()), Demand::getMaxTraineesMumber,
                        dto.getMaxTraineesMumberMax())
                .like(StringUtils.isNotBlank(dto.getContactPerson()), Demand::getContactPerson, dto.getContactPerson());
    }


    private void setPage(IPage<DemandPageVO> copy, List<Unit> units) {
        for (DemandPageVO record : copy.getRecords()) {
            setList(units, record);
        }
    }

    private void setList(List<Unit> units, DemandPageVO record) {
        int total = 0;
        List<DemandTotalVO> voList = new ArrayList<DemandTotalVO>();
        for (Unit unit : units) {
            DemandTotalVO vo = new DemandTotalVO();
            vo.setUnitId(unit.getUnitId());
            vo.setUnitName(unit.getUnitName());
            vo.setContactPerson(unit.getContactPerson());
            vo.setPhone(unit.getPhone());
            if (StringUtils.equals("1", record.getIsIssue()) || StringUtils.equals("2", record.getIsIssue())) {
                Demand demand = demandService.getOne(
                        new LambdaQueryWrapper<Demand>()
                                .eq(Demand::getCreateDept, unit.getUnitId())
                                .eq(Demand::getParentId, record.getDemandId()));
                if (null != demand) {
                    List<Demand> list1 = demandService.list(new LambdaQueryWrapper<Demand>()
                            .eq(Demand::getParentId, demand.getDemandId()));
                    if (CollectionUtils.isNotEmpty(list1)) {
                        List<Demand> list = demandService.getList(list1).stream().filter(l ->
                                StringUtils.equals("1", l.getIsReport()) && 1 == l.getStatus()
                        ).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(list)) {
                            List<DemandSignUp> demandSignUpList = demandSignUpService.list(new LambdaQueryWrapper<DemandSignUp>()
                                    .eq(DemandSignUp::getStatus, 1)
                                    .in(DemandSignUp::getDemandId,
                                            list.stream().map(Demand::getDemandId).collect(Collectors.toList())));
                            if (CollectionUtils.isNotEmpty(demandSignUpList)) {
                                BigDecimal reduce = demandSignUpList.stream().map(l ->
                                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getForecastAttendance()) ?
                                                        "0" : l.getForecastAttendance())))
                                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                                vo.setPeopleNum(reduce.intValue());
                                total = total + reduce.intValue();
                            } else {
                                vo.setPeopleNum(0);
                            }
                        } else {
                            vo.setPeopleNum(0);
                        }
                    } else {
                        vo.setPeopleNum(0);
                    }
                } else {
                    vo.setPeopleNum(0);
                }
            } else {
                vo.setPeopleNum(0);
            }
            voList.add(vo);
        }
        record.setStatistics(voList);
        record.setTotal(String.valueOf(total));
    }


    private void saveBatch(Long d, Demand copy) {
        Unit unit = unitService.getById(d);
        Demand byId = demandService.getById(copy.getDemandId());
        Demand demand = Objects.requireNonNull(BeanUtil.copy(byId, Demand.class))
                .setCreateUser(getUserId())
                .setCreateTime(new Date())
                .setDemandId(null)
                .setParentId(byId.getDemandId())
                .setCreateDept(unit.getUnitId());
        demandService.save(demand);
        demandTotalService.save(new DemandTotal()
                .setDemandId(demand.getDemandId())
                .setUnitId(unit.getUnitId())
                .setUnitName(unit.getUnitName())
                .setContactPerson(unit.getContactPerson())
                .setPhone(unit.getPhone())
                .setPeopleNum(0));
        waitDoneService.save(new WaitDone().setWaitDoneUnit(d)
                .setFlightId(demand.getFlightId())
                .setFlightName(demand.getFlightName())
                .setType("0")
                .setWaitDoneMessage("需求下发待办提示,点击跳转需求类并修改状态")
                .setSkip("")
                .setBusinessId(demand.getDemandId())
                .setCreateDept(getUnitId())
                .setStatus(Constants.ZERO));
        List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getParentId, d));
        if (CollectionUtils.isNotEmpty(units)) {
            units.forEach(u -> saveBatch(u.getUnitId(), demand));
        }
    }

    private void updateBatch(Demand demand) {
        demandService.updateById(demand);
        List<Demand> list = demandService.list(new LambdaQueryWrapper<Demand>()
                .eq(Demand::getParentId, demand.getDemandId()));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(l -> updateBatch(l.setIsIssue(demand.getIsIssue())));
        }
    }

    private void updateBatch(List<Demand> list, DemandUpdateNewDTO dto) {
        List<Demand> list1 = demandService.list(new LambdaQueryWrapper<Demand>()
                .in(Demand::getParentId,
                        list.stream().map(Demand::getDemandId).collect(Collectors.toList())));
        if (CollectionUtils.isNotEmpty(list1)) {
            demandService.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 deleteBatch(List<Demand> list) {
        List<Demand> list1 = demandService.list(new LambdaQueryWrapper<Demand>()
                .in(Demand::getParentId,
                        list.stream().map(Demand::getDemandId).collect(Collectors.toList())));
        if (CollectionUtils.isNotEmpty(list1)) {
            demandService.removeByIds(list1.stream().map(Demand::getDemandId).collect(Collectors.toList()));
            demandTotalService.remove(new LambdaQueryWrapper<DemandTotal>()
                    .in(DemandTotal::getDemandId, list1.stream().map(Demand::getDemandId).collect(Collectors.toList())));
            demandSignUpService.remove(new LambdaQueryWrapper<DemandSignUp>()
                    .in(DemandSignUp::getDemandId, list1.stream().map(Demand::getDemandId).collect(Collectors.toList())));
            deleteBatch(list1);
        }
    }

}
