package com.dayou.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dayou.common.BaseEntity;
import com.dayou.dto.*;
import com.dayou.entity.*;
import com.dayou.enums.MainBusinessEnum;
import com.dayou.enums.ProductionEnum;
import com.dayou.enums.ReportStatus;
import com.dayou.enums.TakeNumberEnum;
import com.dayou.enums.workflow.NodeLogEnum;
import com.dayou.exception.ErrorCode;
import com.dayou.mapper.*;
import com.dayou.message.annotation.SendMessage;
import com.dayou.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dayou.service.workflow.IWorkFlowNodeInstanceService;
import com.dayou.utils.LoginContext;
import com.dayou.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.transaction.annotation.Transactional;

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

import static com.dayou.common.Constants.*;
import static com.dayou.enums.ProductionEnum.*;
import static com.dayou.message.MessageTypeEnum.*;

/**
 * <p>
 * 大中型产品 服务实现类
 * </p>
 *
 * @author wucl
 * @since 2023-11-06
 */
@DS("mbs")
@Slf4j
@Service
public class MajorProductionServiceImpl extends ServiceImpl<MajorProductionMapper, MajorProduction> implements IMajorProductionService {

    private static final BigDecimal EVALUATE_MIN = new BigDecimal("50000000");

    private static final BigDecimal EVALUATE_MAX = new BigDecimal("150000000");

    @Autowired
    private IMajorTargetService majorTargetService;


    @Autowired
    private MajorProductionMapper majorProductionMapper;

    @Autowired
    private IMajorService majorService;

    @Autowired
    private IProductionFundService productionFundService;

    @Autowired
    private IProductionOutWarehouseService outWarehouseService;

    @Autowired
    private IFinanceClaimService financeClaimService;

    @Autowired
    private OrderFundMapper orderFundMapper;

    @Autowired
    private ProductionFundMapper productionFundMapper;

    @Autowired
    private WorkTaskRecordMapper workTaskRecordMapper;

    @Autowired
    private WorkFlowNodeInstanceMapper workFlowNodeInstanceMapper;

    @Autowired
    private WorkFlowLogMapper workFlowLogMapper;

    @Autowired
    private IBusinessFileService businessFileService;

    @Autowired
    private IMajorProductionService majorProductionService;

    @Autowired
    private IBusinessProductionService businessProductionService;

    @Autowired
    private IOrderFundAllotService orderFundAllotService;

    @Autowired
    private IWorkFlowNodeInstanceService workFlowNodeInstanceService;



    @Override
    @SuppressWarnings("unchecked")
    public List<MajorProduction> selectPage(MajorProduction majorProduction){
        List<MajorProduction> list = majorProductionMapper.getList(majorProduction);
        if(CollectionUtils.isNotEmpty(list)){
            MajorProduction production = list.get(0);
            String reportNo = production.getReportNo();
            String productionType = production.getProduction();
            Boolean ifReverse = workFlowNodeInstanceService.checkIfReverse(productionType, reportNo);
            list.stream().forEach(x->{
                x.setSignatoryId(JSON.parseArray(x.getSignatory(),Long.class));
                x.setIfReverse(ifReverse);
            });
        }
        return list;
    }


    @Override
    public MajorProduction detail(Long id){
        return this.getById(id);
    }

    @Override
    public Boolean add(MajorProduction taskData){
        String reportNo = taskData.getReportNo();
        String statementNo = taskData.getStatementNo();
        Long majorId = taskData.getMajorId();
        //查询是否生成过该报告的产品
        MajorProduction prod = this.getOne(new LambdaQueryWrapper<MajorProduction>().eq(MajorProduction::getReportNo, reportNo)
                .eq(MajorProduction::getMajorId, majorId).eq(BaseEntity::getDeleted, Boolean.FALSE));
        if (prod!=null){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,ProductionEnum.valueOf(taskData.getProduction()).getMsg() + "类型产品已存在,请完善产品信息。");
        }
        //查询该流程生成过的价值意见书产品信息
        if (StrUtil.isNotBlank(statementNo)){
            MajorProduction statementProd = this.getOne(new LambdaQueryWrapper<MajorProduction>().eq(MajorProduction::getReportNo, statementNo)
                    .eq(MajorProduction::getMajorId, majorId).eq(BaseEntity::getDeleted, Boolean.FALSE));
            if (statementProd != null){
                taskData.setValueTiming(statementProd.getValueTiming());
                if (StrUtil.isBlank(taskData.getOwner())){
                    taskData.setOwner(statementProd.getOwner());
                }
            }

        }

        //创建出入库二维码
        taskData.setQrCode(businessProductionService.doCreateNormalCode(taskData.getProduction(),reportNo));
        taskData.setStandardAmount(productionFundService.calculateStandardAmount(taskData.getEvaluateAmount()));
        this.save(taskData);

        //创建验证二维码
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getValidateCode,
                businessProductionService.doCreateValidateCode(MainBusinessEnum.MAJOR_BUSINESS,taskData.getId(),taskData.getReportNo()))
                    .eq(BaseEntity::getId,taskData.getId()));
    }

    @Override
    public Boolean finishAllProductionInfo(TaskRecordDTO<MajorProduction> majorProduction){
        MajorProduction taskData = majorProduction.getTaskData();
        return this.update(taskData);
    }

    @Override
    public Boolean update(MajorProduction taskData) {
        String reportNo = taskData.getReportNo();
        Major major = majorService.getOne(new LambdaQueryWrapper<Major>().eq(BaseEntity::getId, taskData.getMajorId())
                .select(BaseEntity::getId, Major::getEvaluateAim,Major::getBusinessObjectType));
        taskData.setBusinessObjectType(major.getBusinessObjectType());
        checkingRule(taskData);
        List<MajorTarget> targets = null;
        String productionType = taskData.getProduction();

        if (productionType.equals(STATEMENT.name())){
            targets = majorTargetService.list(new LambdaQueryWrapper<MajorTarget>()
                    .eq(MajorTarget::getStatementNo, reportNo).eq(BaseEntity::getDeleted, Boolean.FALSE));
        }
        if (productionType.equals(REPORT.name())){
            targets = majorTargetService.list(new LambdaQueryWrapper<MajorTarget>()
                    .eq(MajorTarget::getReportNo, reportNo).eq(BaseEntity::getDeleted, Boolean.FALSE));
        }
        if (productionType.equals(LETTER.name())){
            targets = majorTargetService.list(new LambdaQueryWrapper<MajorTarget>()
                    .eq(MajorTarget::getLetterNo, reportNo).eq(BaseEntity::getDeleted, Boolean.FALSE));
        }

        if (CollectionUtils.isEmpty(targets)){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"还未添加估价对象。");
        }

        if (productionType.equals(REPORT.name())){
            List<Long> signatoryId = taskData.getSignatoryId();
            if (signatoryId.size()>3){
                ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"签字人数不能超过3人。");
            }
            taskData.setSignatory(JSON.toJSONString(signatoryId));
            taskData.setProduction(REPORT.name());
        }

        return  this.updateById(taskData);
    }

    @Override
    public Boolean delete(Long id){
        //逻辑删除
        return this.removeById(id);
    }

    @Override
    public Boolean uploadProductionAttachment(TaskRecordDTO<BusinessFile> taskRecordDTO) {
        BusinessFile file = taskRecordDTO.getTaskData();
        file.setUserId(LoginContext.getCurrentUserId());
        return businessFileService.save(file);
    }

    @SendMessage(messageType = MAJOR_OUT_REPERTORY_REMIND)
    @Override
    public Boolean warehouse(TaskRecordDTO<WareHouseDTO> taskRecordDTO) {
        WareHouseDTO taskData = taskRecordDTO.getTaskData();
        String reportNo = taskData.getReportNo();
        String productionType = taskData.getProductionType();
        MajorProduction production = this.getOne(new LambdaQueryWrapper<MajorProduction>().select(BaseEntity::getId, MajorProduction::getRepertoryState,
                MajorProduction::getReportNo,MajorProduction::getMajorId,MajorProduction::getProduction).eq(BaseEntity::getId,taskData.getProductionId()).eq(BaseEntity::getDeleted, Boolean.FALSE));
        if (production == null) {
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "产品不存在，操作失败。");
        }
        if (!production.getReportNo().equals(reportNo)){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "出库的产品报告号与当前操作的产品报告号不一致，请检查。");
        }
        if (!production.getProduction().equals(productionType)){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "出库的产品类型与当前操作的产品类型不符，请检查。");
        }
        //出库
        if (taskData.getRepertoryState()) {
            if (production.getRepertoryState() == null) {
                ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "产品还未入库，无法出库。");
            }

            if (production.getRepertoryState() != null && production.getRepertoryState()) {
                ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "产品已出库，无法再次出库。");
            }
            if (!production.getProduction().equals(STATEMENT.name())){
                //非价值意见书 需做出库前校验
                Long outId = beforeOutCheck(production);
                //更新申请记录中的出库状态
                if (outId!=null){
                    outWarehouseService.update(new LambdaUpdateWrapper<ProductionOutWarehouse>().set(ProductionOutWarehouse::getProductionOut,Boolean.TRUE).eq(BaseEntity::getId,outId));
                    return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getRepertoryState, Boolean.TRUE)
                            .set(MajorProduction::getRepertoryOutTime,new Date()).eq(BaseEntity::getId, production.getId()));
                }else{
                    ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "财务部未审核或审核不通过，产品暂时无法出库。");
                    return Boolean.FALSE;
                }
            }else{
                //价值意见书出库无需申请审核
                return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getRepertoryState, Boolean.TRUE).set(MajorProduction::getRepertoryOutTime,new Date())
                        .eq(BaseEntity::getId, production.getId()));
            }

        }
        //入库
        else {
            if (production.getRepertoryState() != null && production.getRepertoryState()) {
                ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "产品已出库，请确认产品状态。");
            }

            if (production.getRepertoryState() != null && !production.getRepertoryState()) {
                ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR, "产品已入库，无需再次入库");
            }
            return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getRepertoryState, Boolean.FALSE).set(MajorProduction::getRepertoryInTime,new Date())
                    .eq(BaseEntity::getId, production.getId()));
        }
    }

    @Override
    public Page<MajorProductionVO> getHouse(Page page, MajorProductionVO majorProduction,String keyword) {
        Page<MajorProductionVO> ret = this.majorProductionMapper.getHouse(page,majorProduction, keyword);
        return ret;
    }

    @Override
    public Page<MajorOrderVO> myOrder(Page page, MajorOrderVO myOrder,String keyword) {
        myOrder.setClientManagerId(LoginContext.getCurrentUserId());
        Page<MajorOrderVO> ret = majorProductionMapper.myOrder(page,myOrder,keyword);
        return ret;
    }

    @Override
    public List<MajorOrderVO> exportMyOrder(MajorOrderVO myOrder, String keyword) {
        myOrder.setClientManagerId(LoginContext.getCurrentUserId());
        return majorProductionMapper.exportMyOrder(myOrder, keyword);
    }

    @Override
    public Page<MajorOrderVO> waitingClaim(Page page, MajorOrderVO myOrder) {
        myOrder.setClientManagerId(LoginContext.getCurrentUserId());
        Page<MajorOrderVO> ret = majorProductionMapper.waitingClaim(page,myOrder);
        return ret;
    }

    @Override
    public OrderProductionsBag productionBag(Long id) {
        OrderProductionsBag orderProductionsBag = new OrderProductionsBag();
        orderProductionsBag.setBusinessId(id);
        orderProductionsBag.setBusinessType(MainBusinessEnum.MAJOR_BUSINESS.name());
        List<MajorProduction> list = majorProductionMapper.getMajorProductionAboutFundId(id);
        List<ProductionDTO> productions = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(list)){
            for(MajorProduction production : list ){
                ProductionDTO productionDTO = new ProductionDTO();
                BeanUtil.copyProperties(production,productionDTO);
                productionDTO.setProductionNo(production.getReportNo());
                productions.add(productionDTO);
            }
        }
        orderProductionsBag.setProductions(productions);
        return orderProductionsBag;
    }

    @Override
    public Boolean confirmDelivery(TaskRecordDTO<Long> taskRecordDTO) {
        Long id = taskRecordDTO.getTaskData();
        if (id!=null){
            boolean update = this.update(new LambdaUpdateWrapper<MajorProduction>()
                    .set(MajorProduction::getDelivery, Boolean.TRUE)
                    .set(MajorProduction::getDeliveryDate,new Date()).eq(BaseEntity::getId, id));
            return update;
        }
        return Boolean.FALSE;
    }

    @Override
    public List<OrderReportDTO> getOrderReport(List<OrderReportDTO> claimOrders) {
        if (CollectionUtil.isNotEmpty(claimOrders)){
            for (OrderReportDTO orderReportDTO : claimOrders){
                List<ReportDTO> list = productionFundMapper.getProductionFundByOrderFundId(orderReportDTO.getOrderFundId());
                list.removeAll(Collections.singleton(null));
                orderReportDTO.setReports(list);
            }
        }
        return claimOrders;
    }

    @Override
    public synchronized Boolean allotRealAmount(List<OrderReportDTO> claimOrders) {
        return majorProductionService.doAllotRealAmount(claimOrders);
    }

    @Override
    @SendMessage(messageType = MAJOR_ALLOT_COMMISSION_REMIND1)
    @Transactional
    public Boolean doAllotRealAmount(List<OrderReportDTO> claimOrders){
        if (CollectionUtil.isNotEmpty(claimOrders)){
            //先校验各订单此次认领金额之和是否大于这笔实收款的剩余金额
            Long financeFundId = claimOrders.get(0).getFinanceFundId();
            BigDecimal residueAmount = financeClaimService.checkFinanceFound(financeFundId);
            BigDecimal thisTimeTotalAmount = claimOrders.stream().map(OrderReportDTO::getThisTimeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (thisTimeTotalAmount.compareTo(residueAmount)>0){
                ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"本次订单认领之和大于实收款剩余金额，请检查后再认领。");
                return Boolean.FALSE;
            }

            for (OrderReportDTO orderReportDTO : claimOrders){
                BigDecimal thisTimeAmount = orderReportDTO.getThisTimeAmount();
                if (thisTimeAmount==null || thisTimeAmount.compareTo(BigDecimal.ZERO)==0){
                    continue;
                }
                Long productionFundId = orderReportDTO.getProductionFundId();
                if (productionFundId==null){
                    MajorProduction production = majorProductionMapper.selectOne(new LambdaQueryWrapper<MajorProduction>().eq(BaseEntity::getId,orderReportDTO.getId()).eq(BaseEntity::getDeleted, Boolean.FALSE)
                            .select(MajorProduction::getReportNo, MajorProduction::getMajorId, MajorProduction::getProduction, MajorProduction::getEvaluateAmount,MajorProduction::getStandardAmount));
                    ProductionFund productionFund = new ProductionFund();
                    productionFund.setProductionType(production.getProduction());
                    productionFund.setBusinessType(MainBusinessEnum.MAJOR_BUSINESS.name());
                    productionFund.setOrderFundId(orderReportDTO.getOrderFundId());
                    productionFund.setBusinessId(production.getMajorId());
                    productionFund.setProductionNo(production.getReportNo());
                    productionFund.setRealAmount(thisTimeAmount);
                    productionFund.setEvaluateAmount(production.getEvaluateAmount());
                    productionFund.setStandardAmount(production.getStandardAmount());
                    productionFundService.save(productionFund);
                    productionFundId = productionFund.getId();
                }else {
                    productionFundMapper.updateRealAmount(productionFundId,orderReportDTO.getThisTimeAmount());
                }

                //更新订单实收款
                Long orderFundId = orderReportDTO.getOrderFundId();
                orderFundMapper.updateRealAmount(orderFundId, thisTimeAmount);

                //插入订单认领流水表
                FinanceClaim financeClaim = new FinanceClaim();
                Long userId = LoginContext.getCurrentUserId();
                financeClaim.setClaimUserId(userId);
                financeClaim.setRealFundId(financeFundId);
                financeClaim.setOrderFundId(orderFundId);
                financeClaim.setClaimAmount(thisTimeAmount);
                financeClaim.setClaimDatetime(new Date());
                financeClaim.setProductionFundId(productionFundId);
                financeClaimService.save(financeClaim);
            }
           return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }


    @Override
    public synchronized Boolean allotRealAmountToOrder(List<OrderReportDTO> claimOrders) {
        return majorProductionService.doAllotRealAmountToOrder(claimOrders);
    }


    @Override
    @Transactional
    public Boolean doAllotRealAmountToOrder(List<OrderReportDTO> claimOrders) {
        if (CollectionUtil.isNotEmpty(claimOrders)){
            //先校验各订单此次认领金额之和是否大于这笔实收款的剩余金额
            Long financeFundId = claimOrders.get(0).getFinanceFundId();
            BigDecimal residueAmount = financeClaimService.checkFinanceFound(financeFundId);
            BigDecimal thisTimeTotalAmount = claimOrders.stream().map(OrderReportDTO::getThisTimeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (thisTimeTotalAmount.compareTo(residueAmount)>0){
                ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"本次订单认领之和大于实收款剩余金额，请检查后再认领。");
                return Boolean.FALSE;
            }

            for (OrderReportDTO orderReportDTO : claimOrders){
                BigDecimal thisTimeAmount = orderReportDTO.getThisTimeAmount();
                if (thisTimeAmount==null || thisTimeAmount.compareTo(BigDecimal.ZERO)==0){
                    continue;
                }
                //更新订单实收款
                Long orderFundId = orderReportDTO.getOrderFundId();
                orderFundMapper.updateRealAmount(orderFundId, thisTimeAmount);

                //插入订单认领流水表
                FinanceClaim financeClaim = new FinanceClaim();
                Long userId = LoginContext.getCurrentUserId();
                financeClaim.setClaimUserId(userId);
                financeClaim.setRealFundId(financeFundId);
                financeClaim.setOrderFundId(orderFundId);
                financeClaim.setClaimAmount(thisTimeAmount);
                financeClaim.setClaimDatetime(new Date());
                financeClaimService.save(financeClaim);
            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean noTaskConfirmDelivery(Long id) {
        boolean update = this.update(new LambdaUpdateWrapper<MajorProduction>()
                .set(MajorProduction::getDelivery, Boolean.TRUE)
                .set(MajorProduction::getDeliveryDate,new Date()).eq(BaseEntity::getId, id));
        return update;
    }

    @Override
    public List<MajorProduction> getPendingList(MajorProduction majorProduction) {
        List<MajorProduction> list = majorProductionMapper.getPendingList(majorProduction);
        if(CollectionUtils.isNotEmpty(list)){
            list.stream().forEach(x->{
                x.setSignatoryId(JSON.parseArray(x.getSignatory(),Long.class));
            });
        }
        return list;
    }

    @Override
    public void updateEvaluateAmountAndCheckState(MajorProduction majorProduction) {
        checkingRule(majorProduction);
        this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getEvaluateAmount,majorProduction.getEvaluateAmount())
                .set(MajorProduction::getSecondCheck,majorProduction.getSecondCheck())
                .set(MajorProduction::getThirdCheck,majorProduction.getThirdCheck()).eq(BaseEntity::getId,majorProduction.getId()));
    }

    @Override
    public Page<TaskTodoVO> todoSaveFilePage(Page page, TaskTodoVO todoVO,String keyword) {
        todoVO.setHandlerId(LoginContext.getCurrentUserId());
        Page<TaskTodoVO> ret = majorProductionMapper.todoSaveFilePage(page,todoVO,keyword);
        return ret;
    }

    /**
     * 复审三审规则
     * @param majorProduction
     */
    private void checkingRule(MajorProduction majorProduction) {
        String evaluateAim = majorProduction.getWorkPurpose();
        BigDecimal evaluateAmount = majorProduction.getEvaluateAmount();
        String businessObjectType = majorProduction.getBusinessObjectType();
        String production = majorProduction.getProduction();
        if (evaluateAim.equals(RENT)){
            majorProduction.setSecondCheck(ReportStatus.不审.name());
            majorProduction.setThirdCheck(ReportStatus.不审.name());
        }else {
            if (evaluateAim.equals(PLEDGE)){
                if (businessObjectType.equals(TakeNumberEnum.LAND_NUMBER.getType())){
                    if (majorProduction.getIsRecord() && REPORT.name().equals(production)){
                        majorProduction.setSecondCheck(ReportStatus.待审核.name());
                        majorProduction.setThirdCheck(ReportStatus.待审核.name());
                    }else{
                        if (evaluateAmount.compareTo(EVALUATE_MIN)<=0){
                            majorProduction.setSecondCheck(ReportStatus.不审.name());
                            majorProduction.setThirdCheck(ReportStatus.不审.name());
                        }else if (evaluateAmount.compareTo(EVALUATE_MAX)<=0
                                && evaluateAmount.compareTo(EVALUATE_MIN)>0){
                            majorProduction.setSecondCheck(ReportStatus.待审核.name());
                            majorProduction.setThirdCheck(ReportStatus.不审.name());
                        }else {
                            majorProduction.setSecondCheck(ReportStatus.待审核.name());
                            majorProduction.setThirdCheck(ReportStatus.待审核.name());
                        }
                    }
                }else{
                    if (evaluateAmount.compareTo(EVALUATE_MIN)<=0){
                        majorProduction.setSecondCheck(ReportStatus.不审.name());
                        majorProduction.setThirdCheck(ReportStatus.不审.name());
                    }else if (evaluateAmount.compareTo(EVALUATE_MAX)<=0
                            && evaluateAmount.compareTo(EVALUATE_MIN)>0){
                        majorProduction.setSecondCheck(ReportStatus.待审核.name());
                        majorProduction.setThirdCheck(ReportStatus.不审.name());
                    }else {
                        majorProduction.setSecondCheck(ReportStatus.待审核.name());
                        majorProduction.setThirdCheck(ReportStatus.待审核.name());
                    }
                }
            }
            else{
                majorProduction.setSecondCheck(ReportStatus.待审核.name());
                majorProduction.setThirdCheck(ReportStatus.待审核.name());
            }
        }
    }

    @Override
    @Transactional
    public Boolean batchSaveFile(List<TaskTodoVO> todoVOList) {
        if (CollectionUtil.isNotEmpty(todoVOList)){
            try {
                //1.完成任务记录
                List<Long> taskIds = todoVOList.stream().map(TaskTodoVO::getTaskId).collect(Collectors.toList());
                workTaskRecordMapper.batchFinishTask(taskIds);
                //2.提交节点状态
                List<Long> currentNodeIds = todoVOList.stream().map(TaskTodoVO::getCurrentNodeId).collect(Collectors.toList());
                workFlowNodeInstanceMapper.batchCommitNode(currentNodeIds);
                //3.更新产品归档信息
                List<Long> productionIds = todoVOList.stream().map(TaskTodoVO::getProductionId).collect(Collectors.toList());
                majorProductionMapper.updateSaveFileInfo(productionIds);
                //4.添加日志
                Long currentUserId = LoginContext.getCurrentUserId();
                List<WorkFlowLog> workFlowLogs = todoVOList.stream().map(x -> {
                    WorkFlowLog log = new WorkFlowLog();
                    log.setBusinessId(x.getBusinessId());
                    log.setBusinessType(MainBusinessEnum.MAJOR_BUSINESS.name());
                    log.setHandingTime(new Date().getTime() - x.getTaskCreated().getTime());
                    log.setHandlerId(currentUserId);
                    log.setState(NodeLogEnum.PASS.name());
                    log.setInstanceId(x.getCurrentNodeId());
                    log.setBusinessSubId(x.getBusinessSubId());
                    log.setBusinessMinId(x.getBusinessMinId());
                    return log;
                }).collect(Collectors.toList());
                workFlowLogMapper.insertBatch(workFlowLogs);
                return Boolean.TRUE;
            } catch (Exception e) {
               ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"归档数据错误，请联系系统管理员。");
                return Boolean.FALSE;
            }
        }
        ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"归档报告为空，请检查归档报告。");
        return Boolean.FALSE;
    }

    @Override
    public List<ReportDTO> getProductionByOrderFundId(Long orderFundId) {
        List<ReportDTO> list = productionFundMapper.getProductionFundByOrderFundId(orderFundId);
        list.removeAll(Collections.singleton(null));
        return list;
    }

    @Override
    public synchronized  Boolean allotRealAmountToProduction(OrderReportDTO orderReportDTO){
        return majorProductionService.doAllotRealAmountToProduction(orderReportDTO);
    }
    @Override
    @SendMessage(messageType = MAJOR_ALLOT_COMMISSION_REMIND2 )
    @Transactional
    public  Boolean doAllotRealAmountToProduction(OrderReportDTO orderReportDTO) {
        List<ReportDTO> reports = orderReportDTO.getReports();
        Long orderFundId = orderReportDTO.getOrderFundId();
        BigDecimal residueAmount = orderFundMapper.residueNotAllotAmount(orderFundId);
        BigDecimal totalAmount = reports.stream().filter(x->x.getThisTimeAmount()!=null).map(ReportDTO::getThisTimeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (orderReportDTO.getRealAmount()==null){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"该订单还未认领实收款，请先认领实收款后再分配。");
        }
        if (totalAmount.compareTo(residueAmount)>0){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"产品分配金额不能大于订单未分配金额，请检查后再试。");
        }
        if (CollectionUtil.isNotEmpty(reports)){
            for (ReportDTO reportDTO :reports){
                Long productionFundId = reportDTO.getProductionFundId();
                if (reportDTO.getThisTimeAmount()==null || reportDTO.getThisTimeAmount().compareTo(BigDecimal.ZERO)==0){
                    continue;
                }
                //产品收款表
                if (productionFundId==null){
                    MajorProduction production = majorProductionMapper.selectOne(new LambdaQueryWrapper<MajorProduction>().eq(BaseEntity::getId,reportDTO.getId()).eq(BaseEntity::getDeleted, Boolean.FALSE)
                            .select(MajorProduction::getReportNo, MajorProduction::getMajorId, MajorProduction::getProduction, MajorProduction::getEvaluateAmount));
                    ProductionFund productionFund = new ProductionFund();
                    productionFund.setProductionType(production.getProduction());
                    productionFund.setBusinessType(MainBusinessEnum.MAJOR_BUSINESS.name());
                    productionFund.setOrderFundId(orderReportDTO.getOrderFundId());
                    productionFund.setBusinessId(production.getMajorId());
                    productionFund.setProductionNo(production.getReportNo());
                    productionFund.setRealAmount(reportDTO.getThisTimeAmount());
                    productionFund.setEvaluateAmount(production.getEvaluateAmount());
                    productionFundService.save(productionFund);
                    productionFundId = productionFund.getId();
                }else {
                    productionFundMapper.updateRealAmount(productionFundId,reportDTO.getThisTimeAmount());
                }
                //分配记录表
                OrderFundAllot orderFundAllot = new OrderFundAllot();
                orderFundAllot.setProductionFundId(productionFundId);
                orderFundAllot.setOrderFundId(orderFundId);
                orderFundAllot.setAllotAmount(reportDTO.getThisTimeAmount());
                orderFundAllotService.save(orderFundAllot);

            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }


    @Override
    public Page<MajorProductionPerformanceVO> performanceAllotPage(Page page, MajorProductionPerformanceVO productionPerformance,String keyword) {
        Page<MajorProductionPerformanceVO> result = majorProductionMapper.performanceAllotPage(page,productionPerformance, keyword);
        return result;
    }

    @Override
    public Page<MajorProductionVO> waitingClaimProd(Page page, MajorProductionVO production) {
        production.setClientManagerId(LoginContext.getCurrentUserId());
        Page<MajorProductionVO> result = majorProductionMapper.waitingClaimProd(page,production);
        return result;
    }



    @Override
    public Boolean repertoryIn(TaskRecordDTO<Long> taskRecordDTO) {
        Long productionId = taskRecordDTO.getTaskData();
        MajorProduction production = this.getOne(new LambdaQueryWrapper<MajorProduction>().select(MajorProduction::getRepertoryState).eq(BaseEntity::getId, productionId).eq(BaseEntity::getDeleted, Boolean.FALSE));

        if (production==null){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"产品不存在，入库失败。");
        }

        if (production.getRepertoryState()!=null && production.getRepertoryState()){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"产品已出库，请确认产品状态。");
        }

        if (production.getRepertoryState()!=null && !production.getRepertoryState()){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"产品已入库，无需再次入库");
        }
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getRepertoryState,Boolean.FALSE).eq(BaseEntity::getId,productionId));
    }

    @Transactional
    @Override
    public Boolean repertoryOut(TaskRecordDTO<Long> taskRecordDTO) {
        Long productionId = taskRecordDTO.getTaskData();

        MajorProduction production = this.getOne(new LambdaQueryWrapper<MajorProduction>()
                .select(MajorProduction::getRepertoryState,MajorProduction::getMajorId,MajorProduction::getReportNo,MajorProduction::getProduction)
                .eq(BaseEntity::getId, productionId).eq(BaseEntity::getDeleted, Boolean.FALSE));
        if (production==null){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"产品不存在，出库失败。");
        }
        if (production.getRepertoryState()==null){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"产品还未入库，无法出库。");
        }
        if (production.getRepertoryState()!=null && production.getRepertoryState()){
            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"产品已出库，无法再次出库。");
        }
        //出库前校验
        Long outId = beforeOutCheck(production);
        //更新申请记录中的出库状态
        if (outId!=null){
            outWarehouseService.update(new LambdaUpdateWrapper<ProductionOutWarehouse>().set(ProductionOutWarehouse::getProductionOut,Boolean.TRUE).eq(BaseEntity::getId,outId));
        }
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getRepertoryState,Boolean.TRUE).eq(BaseEntity::getId,productionId));
    }

    private Long beforeOutCheck(MajorProduction production) {
        ProductionOutWarehouse outApply = outWarehouseService.getOne(new LambdaQueryWrapper<ProductionOutWarehouse>()
                .eq(ProductionOutWarehouse::getBusinessType,MainBusinessEnum.MAJOR_BUSINESS.name())
                .eq(ProductionOutWarehouse::getProductionId,production.getId())
                .eq(ProductionOutWarehouse::getReportNo,production.getReportNo())
                .eq(ProductionOutWarehouse::getFinanceCheckState,ReportStatus.审核通过.name())
                .eq(BaseEntity::getDeleted, Boolean.FALSE));
        return outApply.getId();
    }

    @Override
    public Boolean firstCheck(TaskRecordDTO<CommonCheckDTO> taskRecordDTO) {
        CommonCheckDTO taskData = taskRecordDTO.getTaskData();
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getFirstCheck,taskData.getResult())
                .eq(BaseEntity::getId,taskData.getId()));
    }

    @Override
    public Boolean secondCheck(TaskRecordDTO<CommonCheckDTO> taskRecordDTO) {
        CommonCheckDTO taskData = taskRecordDTO.getTaskData();
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getSecondCheck,taskData.getResult())
                .eq(BaseEntity::getId,taskData.getId()));
    }

    @Override
    public Boolean thirdCheck(TaskRecordDTO<CommonCheckDTO> taskRecordDTO) {
        CommonCheckDTO taskData = taskRecordDTO.getTaskData();
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getThirdCheck,taskData.getResult())
                .eq(BaseEntity::getId,taskData.getId()));
    }

    @Override
    public Boolean saveFileCheck(TaskRecordDTO<CommonCheckDTO> taskRecordDTO) {
        CommonCheckDTO taskData = taskRecordDTO.getTaskData();
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getSaveFileCheck,taskData.getCheck())
                .eq(BaseEntity::getId,taskData.getId()));
    }

    @Override
    public Boolean saveFileSecondCheck(TaskRecordDTO<CommonCheckDTO> taskRecordDTO) {
        CommonCheckDTO taskData = taskRecordDTO.getTaskData();
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getSaveFileSecondCheck,taskData.getCheck())
                .eq(BaseEntity::getId,taskData.getId()));
    }

    @Override
    public Boolean saveFile(TaskRecordDTO<Long> taskRecordDTO) {
        Long id = taskRecordDTO.getTaskData();
        return this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getIfSaveFile,Boolean.TRUE)
                .eq(BaseEntity::getId,id));
    }

    @Override
    public Page<MajorProductionSaveDoneVO> saveDonePage(Page page, MajorProductionSaveDoneVO productionDone,String keyword) {
        Page<MajorProductionSaveDoneVO> done = majorProductionMapper.saveDonePage(page,productionDone,keyword);
        return done;
    }


}
