package com.bonus.material.lease.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.bonus.common.biz.constant.GlobalConstants;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.domain.lease.LeaseApplyInfo;
import com.bonus.common.biz.enums.*;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.back.mapper.BackApplyInfoMapper;
import com.bonus.material.basic.domain.BmAgreementInfo;
import com.bonus.material.basic.domain.BmQrBoxInfo;
import com.bonus.material.basic.domain.BmUnit;
import com.bonus.material.basic.mapper.BmAgreementInfoMapper;
import com.bonus.material.basic.mapper.BmQrBoxMapper;
import com.bonus.material.clz.domain.BmTeam;
import com.bonus.material.clz.domain.lease.MaterialLeaseApplyDetails;
import com.bonus.material.clz.domain.lease.MaterialLeaseApplyInfo;
import com.bonus.material.clz.domain.vo.MaterialSltAgreementInfo;
import com.bonus.material.clz.mapper.BmTeamMapper;
import com.bonus.material.clz.mapper.MaterialLeaseInfoMapper;
import com.bonus.material.lease.domain.LeaseApplyDetails;
import com.bonus.material.lease.mapper.LeaseApplyDetailsMapper;
import com.bonus.material.lease.mapper.LeaseApplyInfoMapper;
import com.bonus.material.ma.domain.Type;
import com.bonus.material.ma.mapper.MachineMapper;
import com.bonus.material.ma.mapper.TypeMapper;
import com.bonus.material.ma.service.ITypeService;
import com.bonus.material.settlement.domain.SltAgreementInfo;
import com.bonus.material.settlement.mapper.SltAgreementInfoMapper;
import com.bonus.material.task.domain.TmTask;
import com.bonus.material.task.domain.TmTaskAgreement;
import com.bonus.material.task.mapper.TmTaskAgreementMapper;
import com.bonus.material.task.mapper.TmTaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bonus.material.lease.mapper.LeaseOutDetailsMapper;
import com.bonus.common.biz.domain.lease.LeaseOutDetails;
import com.bonus.material.lease.service.ILeaseOutDetailsService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 领料出库详细Service业务层处理
 *
 * @author xsheng
 * @date 2024-10-16
 */
@Service
@Slf4j
public class LeaseOutDetailsServiceImpl implements ILeaseOutDetailsService {

    // 来源1: 单位直接领用
    private static final Integer DIRECT_RESOURCE = GlobalConstants.INT_1;

    // 来源2: 班组领用同步过来的数据
    private static final Integer SYNC_RESOURCE = GlobalConstants.INT_2;

    @Autowired
    private LeaseApplyInfoMapper leaseApplyInfoMapper;

    @Autowired
    private LeaseOutDetailsMapper leaseOutDetailsMapper;

    @Autowired
    private LeaseApplyDetailsMapper leaseApplyDetailsMapper;

    @Autowired
    private MachineMapper machineMapper;

    @Autowired
    private TypeMapper typeMapper;

    @Autowired
    private TmTaskMapper tmTaskMapper;

    @Autowired
    private SltAgreementInfoMapper sltAgreementInfoMapper;

    @Autowired
    private BmAgreementInfoMapper bmAgreementInfoMapper;

    @Autowired
    private TmTaskAgreementMapper tmTaskAgreementMapper;

    @Resource
    private BmQrBoxMapper bmQrBoxMapper;

    @Resource
    private BmTeamMapper bmTeamMapper;

    @Resource
    private MaterialLeaseInfoMapper materialLeaseInfoMapper;

    @Resource
    private ITypeService typeService;
    /**
     * 查询领料出库详细
     *
     * @param id 领料出库详细主键
     * @return 领料出库详细
     */
    @Override
    public LeaseOutDetails selectLeaseOutDetailsById(Long id) {
        return leaseOutDetailsMapper.selectLeaseOutDetailsById(id);
    }

    /**
     * 查询领料出库详细列表
     *
     * @param leaseOutDetails 领料出库详细
     * @return 领料出库详细
     */
    @Override
    public List<LeaseOutDetails> selectLeaseOutDetailsList(LeaseOutDetails leaseOutDetails) {
        return leaseOutDetailsMapper.selectLeaseOutDetailsList(leaseOutDetails);
    }

    /**
     * 新增领料出库详细
     *
     * @param leaseOutDetailsList 领料出库详细
     * @return 结果
     */
    @Override
    public AjaxResult insertLeaseOutDetails(List<LeaseOutDetails> leaseOutDetailsList) {
        for (LeaseOutDetails bean : leaseOutDetailsList) {
            AjaxResult ajaxResult = leaseOut(bean);
            if (ajaxResult.isError()) {
                return ajaxResult;
            }
        }
        return AjaxResult.success();
    }

    /**
     * 修改领料出库详细
     *
     * @param leaseOutDetails 领料出库详细
     * @return 结果
     */
    @Override
    public int updateLeaseOutDetails(LeaseOutDetails leaseOutDetails) {
        leaseOutDetails.setUpdateTime(DateUtils.getNowDate());
        try {
            return leaseOutDetailsMapper.updateLeaseOutDetails(leaseOutDetails);
        } catch (Exception e) {
            throw new ServiceException("错误信息描述");
        }
    }

    /**
     * 批量删除领料出库详细
     *
     * @param ids 需要删除的领料出库详细主键
     * @return 结果
     */
    @Override
    public int deleteLeaseOutDetailsByIds(Long[] ids) {
        return leaseOutDetailsMapper.deleteLeaseOutDetailsByIds(ids);
    }

    /**
     * 删除领料出库详细信息
     *
     * @param id 领料出库详细主键
     * @return 结果
     */
    @Override
    public int deleteLeaseOutDetailsById(Long id) {
        return leaseOutDetailsMapper.deleteLeaseOutDetailsById(id);
    }

    /**
     * 领料出库处理
     *
     * @param record 出库对象
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult leaseOut(LeaseOutDetails record) {
        int res;
        try {
            // 1、判断库存是否足够
            //boolean isEnough = checkStorageIsEnough(record);
            record.setPreStoreNum(getStorageNum(record));
            /*if (isEnough) {*/
                if ((record.getManageType().equals(MaTypeManageTypeEnum.NUMBER_DEVICE.getTypeId())) && record.getInputNum() != null) {
                    record.setOutNum(record.getInputNum());
                    record.setOutType(InputOutEnum.NUMBER_DEVICE.getTypeId());
                }
                // 检查库存数量是否足够
                res = checkStorageNum(record);

                if (res > GlobalConstants.INT_0) {
                    // 3、插入出库记录，修改库存，修改机具状态
                    res = insertRecords(record);
                    if (res == GlobalConstants.INT_0) {
                        throw new RuntimeException("出库失败,更新设备规格库存数量时出错!");
                    }
                    // 4、修改任务状态（tm_task）
                    res = updateTaskStatus(record);
                    if (res == GlobalConstants.INT_0) {
                        throw new RuntimeException("出库失败,修改任务状态失败");
                    }
                    // 5、插入结算记录
                    String taskId = leaseApplyInfoMapper.getTaskId(record.getParentId());
                    record.setTaskId(taskId);

                    // 判断如果是班组领料，则插入原本项目部的协议结算记录
                    if (record.getLeaseUnitIsTeam() != null && record.getLeaseUnitIsTeam()) {
                        // 设置数据来源是2（班组同步）
                        record.setSource(SYNC_RESOURCE);
                        // 暂存现在出库的班组单位ID
                        Integer thisOutId = record.getLeaseUnitId();
                        // 查询班组挂靠的项目部协议ID
                        Long projectUnitAgreementId = leaseApplyInfoMapper.selectProjectUnitAgreementIdByTeamAndProject(record.getLeaseUnitId(), record.getLeaseProjectId()).getProjectUnitAgreementId();
                        if (projectUnitAgreementId != null && projectUnitAgreementId > GlobalConstants.INT_0) {
                            record.setProjectUnitAgreementId(projectUnitAgreementId);
                        } else {
                            return AjaxResult.error("出库失败,没有找到班组所属项目部协议信息");
                        }
                        // 设置默认可退还数量等同于领用数量，因为班组的协议可以直接去分公司退还, 并设置source来源为2（班组领用）
                        record.setReturnNum(record.getOutNum());
                        // 查询申请领料的项目部单位ID
                        Long originLeaseUnitId = leaseApplyInfoMapper.selectLeaseApplyInfoUnitIdByLeaseId(record.getParentId());
                        record.setLeaseUnitId(Math.toIntExact(originLeaseUnitId));
                        // 插入项目部领料的结算记录
                        int inserts = insSltInfo(taskId, record);
                        System.out.println("插入原本项目部领料结算记录" + (inserts > GlobalConstants.INT_0 ? "成功" : "失败"));

                        // 恢复出库班组单位ID
                        record.setLeaseUnitId(thisOutId);
                        record.setLeaseUnitIsTeam(false);
                        // 设置可退还数量是0，因为默认全部发给班组了，不允许项目部协议直接退，要等班组退还到项目部后才能恢复
                        record.setReturnNum(BigDecimal.ZERO);
                    }
                    // 设置数据来源是1（直领）
                    record.setSource(DIRECT_RESOURCE);
                    res = insSltInfo(taskId, record);
                    if (res == GlobalConstants.INT_0) {
                        throw new RuntimeException("出库失败,插入结算记录失败");
                    }
                    // 6、如果标准箱入库，需要将设备从标准箱移出
                    if (!Objects.isNull(record.getMaId())) {
                        // 先查询设备是否在标准箱中
                        List<BmQrBoxInfo> list = bmQrBoxMapper.selectByMaId(record.getMaId());
                        if (!CollectionUtils.isEmpty(list)) {
                            res = updateBoxBind(record);
                            if (res == GlobalConstants.INT_0) {
                                throw new RuntimeException("出库失败,移出设备失败");
                            }
                        }
                    }
                    // 7.将班组领料数据同步至材料站
                    //7.1 根据单位id判读是否为班组领料出库
                    BmUnit unit = tmTaskMapper.selectBmUnitById(record);
                    if (unit != null && unit.getTypeId() == 1731L) {
                        // 先根据taskId去tm_task中查询，看数据是否存在
                        String createBy = SecurityUtils.getLoginUser().getSysUser().getNickName();
                        TmTask task = tmTaskMapper.selectTmTaskByPreTaskId(Long.parseLong(record.getTaskId()));
                        if (task == null) {
                            int thisMonthMaxOrder = tmTaskMapper.getMonthMaxOrderByDate(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth(), TmTaskTypeEnum.TM_TASK_MATERIAL_LEASE.getTaskTypeId());
                            String taskCode = genderTaskCode(thisMonthMaxOrder);
                            TmTask tmTask = new TmTask(null, TmTaskTypeEnum.TM_TASK_MATERIAL_LEASE.getTaskTypeId(),
                                    LeaseTaskStatusEnum.LEASE_TASK_FINISHED.getStatus(),
                                    null, thisMonthMaxOrder + GlobalConstants.INT_1, taskCode);
                            tmTask.setCreateTime(DateUtils.getNowDate());
                            tmTask.setCreateBy(createBy);
                            tmTask.setPreTaskId(Long.parseLong(record.getTaskId()));
                            tmTaskMapper.insertTmTask(tmTask);
                            BmAgreementInfo bmAgreementInfo = new BmAgreementInfo();
                            bmAgreementInfo.setProjectId(Long.valueOf(record.getLeaseProjectId()));
                            bmAgreementInfo.setCreateTime(DateUtils.getNowDate());
                            bmAgreementInfo.setCreateBy(createBy);
                            bmAgreementInfo.setSignTime(DateUtils.getNowDate());
                            bmAgreementInfo.setAgreementCode(getAgreementCode());
                            // 先根据班组名称查询此班组是否存在
                            BmTeam tbTeam = new BmTeam();
                            tbTeam.setTeamName(record.getLeaseUnit());
                            tbTeam.setProjectId(record.getLeaseProjectId().toString());
                            // 班组类型固定传值
                            tbTeam.setTypeId(1731L);
                            BmTeam bmTeam = bmTeamMapper.selectByName(tbTeam);
                            if (bmTeam == null) {
                                // 新增班组
                                tbTeam.setCreateUser(SecurityUtils.getLoginUser().getUserid().toString());
                                int result = bmTeamMapper.insert(tbTeam);
                                if (result <= GlobalConstants.INT_0) {
                                    return AjaxResult.error(HttpCodeEnum.UPDATE_TO_DATABASE.getCode(), HttpCodeEnum.UPDATE_TO_DATABASE.getMsg());
                                }
                                bmAgreementInfo.setUnitId(tbTeam.getId());
                            } else {
                                bmAgreementInfo.setUnitId(bmTeam.getId());
                                // 修改班组信息
                                bmTeamMapper.update(tbTeam);
                            }
                            // 先根据班组和工程id查询，若存在则直接返回，不存在则新增
                            BmAgreementInfo info = bmAgreementInfoMapper.queryByTeamIdAndProjectIdCl(bmAgreementInfo);
                            if (info != null) {
                                record.setAgreementId(info.getAgreementId());
                            } else {
                                int count = bmAgreementInfoMapper.insertBmAgreementInfoClz(bmAgreementInfo);
                                if (count > GlobalConstants.INT_0) {
                                    record.setAgreementId(bmAgreementInfo.getAgreementId());
                                } else {
                                    return AjaxResult.error("新增bm_agreement_info表失败");
                                }
                            }
                            TmTaskAgreement tmTaskAgreement = new TmTaskAgreement(tmTask.getTaskId(), record.getAgreementId());
                            tmTaskAgreement.setCreateTime(DateUtils.getNowDate());
                            tmTaskAgreement.setCreateBy(createBy);
                            tmTaskAgreementMapper.insertTmTaskAgreement(tmTaskAgreement);
                            // 领料任务类型为2 数据同步
                            MaterialLeaseApplyInfo materialLeaseApplyInfo = new MaterialLeaseApplyInfo();
                            materialLeaseApplyInfo.setCode(taskCode);
                            materialLeaseApplyInfo.setTaskId(tmTask.getTaskId());
                            materialLeaseApplyInfo.setLeaseStyle(SYNC_RESOURCE.toString());
                            materialLeaseApplyInfo.setTeamId(bmAgreementInfo.getUnitId().toString());
                            materialLeaseApplyInfo.setProjectId(record.getLeaseProjectId().toString());
                            materialLeaseApplyInfo.setCreateTime(DateUtils.getNowDate());
                            materialLeaseApplyInfo.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
                            int count = materialLeaseInfoMapper.insertLeaseApplyInfo(materialLeaseApplyInfo);
                            if (count > GlobalConstants.INT_0) {
                                return insertPurchaseCheckDetails(record, createBy, tmTask.getTaskId(), materialLeaseApplyInfo.getId());
                            } else {
                                return AjaxResult.error("新增任务失败,lease_apply_info表插入0条");
                            }
                        } else {
                            // 根据taskId查询领料任务
                            MaterialLeaseApplyInfo info = materialLeaseInfoMapper.selectId(task.getTaskId());
                            // 根据id查询clz_lease_apply_details表中数据是否存在
                            if (info != null) {
                                info.setTypeId(record.getTypeId().toString());
                                record.setParentId(info.getId());
                                record.setCreateTime(DateUtils.getNowDate());
                                record.setCreateBy(createBy);
                                record.setIsFinished(GlobalConstants.INT_1);
                                MaterialLeaseApplyDetails details = materialLeaseInfoMapper.selectDetailsById(info);
                                if (details != null) {
                                    // 走编辑
                                    details.setOutNum(record.getOutNum());
                                    details.setParentId(info.getId());
                                    details.setTypeId(record.getTypeId());
                                    int count = materialLeaseInfoMapper.updateLeaseApplyDetails(details);
                                    if (count < GlobalConstants.INT_1) {
                                        throw new Exception("更新clz_lease_apply_details表数据失败");
                                    }
                                } else {
                                    // 走新增
                                    record.setPreNum(record.getOutNum());
                                    record.setAlNum(record.getOutNum());
                                    res = materialLeaseInfoMapper.insertLeaseApplyDetails(record);
                                    if (res <= GlobalConstants.INT_0) {
                                        throw new Exception("新增clz_lease_apply_details表数据失败");
                                    }
                                }
                                // 根据类型查询clz_lease_out_details表数据是否存在
                                if (record.getMaId() != null) {
                                    // 编码直接走新增
                                    res = materialLeaseInfoMapper.insertLeaseOutDetails(record);
                                    if (res <= GlobalConstants.INT_0) {
                                        throw new Exception("新增clz_lease_out_details表数据失败");
                                    }
                                    res = insSltInfoClz(task.getTaskId(), record);
                                } else {
                                    record.setTypeId(record.getTypeId());
                                    // 数量先判断是否存在，存在则进行数量追加，否则新增
                                    LeaseOutDetails leaseOutDetails = materialLeaseInfoMapper.selectInfoByTypeId(record);
                                    if (leaseOutDetails != null) {
                                        leaseOutDetails.setOutNum(record.getOutNum());
                                        res = materialLeaseInfoMapper.updateLeaseOutDetails(leaseOutDetails);
                                        if (res <= GlobalConstants.INT_0) {
                                            throw new Exception("更新clz_lease_out_details表数据失败");
                                        }
                                    } else {
                                        res = materialLeaseInfoMapper.insertLeaseOutDetails(record);
                                        if (res <= GlobalConstants.INT_0) {
                                            throw new Exception("新增clz_lease_out_details表数据失败");
                                        }
                                    }
                                    res = insSltInfoClz(task.getTaskId(), record);
                                }
                            }
                        }
                    }
                } else {
                    return AjaxResult.error("领料出库失败,机具库存不足");
                }
            /*} else {
                return AjaxResult.error("已领数量大于预领数量或该机具未在库");
            }*/
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error("出库失败" + e.getMessage());
        }
        return AjaxResult.success("出库成功");
    }

    /**
     * 出库同步材料站
     * @param record
     * @param createBy
     * @param taskId
     * @param id
     * @return
     */
    private AjaxResult insertPurchaseCheckDetails(LeaseOutDetails record, String createBy, Long taskId, Long id) {
        record.setCreateTime(DateUtils.getNowDate());
        record.setCreateBy(createBy);
        record.setParentId(id);
        record.setIsFinished(GlobalConstants.INT_1);
        int res = materialLeaseInfoMapper.insertLeaseOutDetails(record);
        if (res == GlobalConstants.INT_0) {
            throw new RuntimeException("出库失败,插入结算记录失败");
        }
        record.setPreNum(record.getOutNum());
        record.setAlNum(record.getOutNum());
        res = materialLeaseInfoMapper.insertLeaseApplyDetails(record);
        if (res == GlobalConstants.INT_0) {
            throw new RuntimeException("出库失败,插入结算记录失败");
        }
        res = insSltInfoClz(taskId, record);
        if (res == GlobalConstants.INT_0) {
            throw new RuntimeException("出库失败,插入结算记录失败");
        }
        return AjaxResult.success("出库成功");
    }

    /**
     * 插入结算记录
     * @param taskId
     * @param record
     * @return
     */
    private int insSltInfoClz(Long taskId, LeaseOutDetails record) {
        int res = GlobalConstants.INT_0;
        MaterialSltAgreementInfo sltAgreementInfo = materialLeaseInfoMapper.getSltAgreementInfo(record);
        if (sltAgreementInfo != null) {
            BigDecimal num = sltAgreementInfo.getNum();
            BigDecimal outNum = record.getOutNum();
            sltAgreementInfo.setNum(num.add(outNum));
            res = materialLeaseInfoMapper.updSltInfo(sltAgreementInfo);
            record.setAgreementId(sltAgreementInfo.getAgreementId());
        } else {
            String agreementId = tmTaskAgreementMapper.getAgreementId(taskId.toString());
            Type maType = typeMapper.getMaType(record.getTypeId());
            maType.setFinalPrice(maType.getLeasePrice());
            record.setLeaseStyle("2");
            res = materialLeaseInfoMapper.insSltInfo(record, agreementId, maType);
        }
        return res;
    }

    /**
     * 生成任务编号
     * @param thisMonthMaxOrder
     * @return
     */
    private static String genderTaskCode(Integer thisMonthMaxOrder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        String result = format.replace("-", "");
        return MaterialConstants.MATERIAL_LEASE_TASK_TYPE_LABEL + result + String.format("-%03d", thisMonthMaxOrder + GlobalConstants.INT_1);
    }

    /**
     * 获取协议编号
     *
     * @return
     */
    private String getAgreementCode() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        String result = format.replace("-", "");
        int num = bmAgreementInfoMapper.selectNumByMonthClz(nowDate);
        return MaterialConstants.AGREEMENT_PREFIX + result + String.format("-%03d", num + GlobalConstants.INT_1);
    }

    /**
     * app领料出库退回
     *
     * @param leaseOutDetails
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult leaseOutBack(LeaseOutDetails leaseOutDetails) {
        int res;
        try {
            // 1 根据任务id查询此任务是否已经完结
            if (StringUtils.isNotBlank(leaseOutDetails.getPublishTask())) {
                // 查询领用出库数据
                LeaseApplyInfo leaseApplyInfo = new LeaseApplyInfo();
                leaseApplyInfo.setPublishTask(leaseOutDetails.getPublishTask());
                List<LeaseApplyInfo> leaseApplyOutList = leaseApplyInfoMapper.selectPublishList(leaseApplyInfo);
                if (!CollectionUtils.isEmpty(leaseApplyOutList)) {
                    for (LeaseApplyInfo applyInfo : leaseApplyOutList) {
                        if (applyInfo.getPreCountNum().compareTo(applyInfo.getAlNum()) == GlobalConstants.INT_0) {
                            return AjaxResult.error("该任务已完成，不能进行退库操作");
                        }
                    }
                }
            } else {
                TmTask tmTask = tmTaskMapper.selectTmTaskByTaskId(Long.valueOf(leaseOutDetails.getTaskId()));
                if (tmTask != null && tmTask.getTaskStatus().equals(LeaseTaskStatusEnum.LEASE_TASK_FINISHED.getStatus())) {
                    return AjaxResult.error("该任务已完成，不能进行退库操作");
                }
            }
            // 2、插入出库记录，修改库存，修改机具状态
            res = updateRecords(leaseOutDetails);
            if (res == GlobalConstants.INT_0) {
                throw new RuntimeException("出库退回失败,更新设备规格库存数量时出错!");
            }
            // 3、修改任务状态（tm_task）
            if (StringUtils.isNotBlank(leaseOutDetails.getTaskId())) {
                res = editTaskStatus(leaseOutDetails);
                if (res == GlobalConstants.INT_0) {
                    throw new RuntimeException("出库退回失败,修改任务状态失败");
                }
            }
            // 4、删除结算记录
            res = deleteSltInfo(leaseOutDetails);
            if (res == GlobalConstants.INT_0) {
                throw new RuntimeException("出库失败,插入结算记录失败");
            }
        } catch (RuntimeException re) {
            return AjaxResult.error("出库退回失败");
        }
        return AjaxResult.success("出库退回成功");
    }

    /**
     * 信息采集领料出库
     * @param record
     * @return
     */
    @Override
    public AjaxResult leaseOutByInfo(LeaseOutDetails record) {
        int res = GlobalConstants.INT_0;
        try {
            if (!CollectionUtils.isEmpty(record.getMaCodeList())) {
                record.setCreateBy(SecurityUtils.getLoginUser().getUserid().toString());
                record.setCreateTime(DateUtils.getNowDate());
                record.setOutNum(record.getInputNum());
                res = leaseOutDetailsMapper.insertLeaseOutDetails(record);
                if (res == GlobalConstants.INT_0) {
                    return AjaxResult.error("出库失败");
                }
                for (LeaseOutDetails leaseOutDetails : record.getMaCodeList()) {
                    // 3、插入出库记录，修改库存，修改机具状态
                    leaseOutDetails.setOutNum(BigDecimal.valueOf(GlobalConstants.INT_1));
                    leaseOutDetails.setParentId(record.getParentId());
                    leaseOutDetails.setPublishTask(StringUtils.isNotBlank(record.getPublishTask()) ? record.getPublishTask() : null);
                    leaseOutDetails.setLeaseUnit(record.getLeaseUnit());
                    leaseOutDetails.setLeaseProject(record.getLeaseProject());
                    res = insertRecordsByInfo(leaseOutDetails);
                    if (res == GlobalConstants.INT_0) {
                        throw new RuntimeException("出库失败,更新设备规格库存数量时出错!");
                    }
                    // 4、修改任务状态（tm_task）
                    res = updateTaskStatus(leaseOutDetails);
                    if (res == GlobalConstants.INT_0) {
                        throw new RuntimeException("出库失败,修改任务状态失败");
                    }
                    // 6、如果标准箱入库，需要将设备从标准箱移出
                    if (leaseOutDetails.getMaId() != null) {
                        // 先查询设备是否在标准箱中
                        List<BmQrBoxInfo> list = bmQrBoxMapper.selectByMaId(leaseOutDetails.getMaId());
                        if (!CollectionUtils.isEmpty(list)) {
                            res = updateBoxBind(leaseOutDetails);
                            if (res == GlobalConstants.INT_0) {
                                throw new RuntimeException("出库失败,移出设备失败");
                            }
                        }
                    }
                }
            } else {
                return AjaxResult.error("机具编码不能为空");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error("出库失败");
        }
        return AjaxResult.success("出库成功");
    }

    /**
     * 信息采集领料出库
     * @param record
     * @return
     */
    private int insertRecordsByInfo(LeaseOutDetails record) {
        int res = GlobalConstants.INT_0;
        // 首先更新领料任务详情表的领料数及状态（lease_apply_details）
        res = leaseApplyDetailsMapper.updateLeaseApplyDetailsOutNum(record);
        LeaseApplyDetails leaseApplyDetails = leaseApplyDetailsMapper.getLeaseApplyDetails(record);
        if (leaseApplyDetails.getPreNum().equals(leaseApplyDetails.getAlNum()) || leaseApplyDetails.getAuditNum().equals(leaseApplyDetails.getAlNum())) {
            leaseApplyDetailsMapper.updateLeaseApplyDetailsByLeaseOutRecord(record);
        }
        if (res > GlobalConstants.INT_0) {
            // 插入领料出库明细表（lease_out_details）
            record.setCreateBy(SecurityUtils.getLoginUser().getUserid().toString());
            res += leaseOutDetailsMapper.insertLeaseOutNum(record);
            record.setIsBack(GlobalConstants.INT_0);
            res += leaseOutDetailsMapper.updateMachine(record);
        }
        return res;
    }

    /**
     * 删除结算记录
     * @param leaseOutDetails
     * @return
     */
    private int deleteSltInfo(LeaseOutDetails leaseOutDetails) {
        return sltAgreementInfoMapper.deleteSltInfo(leaseOutDetails);
    }

    /**
     * 修改任务状态（tm_task）
     * @param leaseOutDetails
     * @return
     */
    private int editTaskStatus(LeaseOutDetails leaseOutDetails) {
        return tmTaskMapper.updateTaskStatus(leaseOutDetails.getTaskId(), LeaseTaskStatusEnum.LEASE_TASK_IN_PROGRESS.getStatus());
    }

    /**
     * 更新出库记录
     * @param leaseOutDetails
     * @return
     */
    private int updateRecords(LeaseOutDetails leaseOutDetails) {
        int res = GlobalConstants.INT_0;
        // 首先更新领料任务详情表的领料数及状态（lease_apply_details）
        leaseOutDetails.setUpdateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        res = leaseApplyDetailsMapper.updateBackDetailsOutNum(leaseOutDetails);
        if (res > GlobalConstants.INT_0) {
            // 删除领料出库明细表（lease_out_details）
            res = leaseOutDetailsMapper.deleteLeaseOutDetails(leaseOutDetails);
            if (res > GlobalConstants.INT_0) {
                // 普通机具减少 (ma_type 设备规格表)的库存数量
                res = typeMapper.addMaTypeStockNum(leaseOutDetails);
                // 更新 (ma_machine 设备表)的状态
                if (leaseOutDetails.getMaId() != null) {
                    machineMapper.updateMaMachineStatus(leaseOutDetails, MaMachineStatusEnum.IN_STORE.getStatus());
                }
            }
        }
        return res;
    }

    /**
     * 标准箱移出设备
     *
     * @param record
     * @return
     */
    private int updateBoxBind(LeaseOutDetails record) {
        return bmQrBoxMapper.deleteBoxBind(record);
    }

    /**
     * 查询操作前后库存
     * @param record
     * @return
     */
    private BigDecimal getStorageNum(LeaseOutDetails record) {
        if (StringUtils.isNull(record)) {
            return BigDecimal.ZERO;
        }
        //判断(ma_type 设备规格表)中的库存够不够出库的
        Type maType = leaseOutDetailsMapper.selectByTypeId(record);
        if (maType != null) {
            if ("1".equals(maType.getManageType())) {
                return maType.getStorageNum();
            } else {
                return BigDecimal.valueOf(leaseOutDetailsMapper.getCountOfCodeMachine(record));
            }
        }
        return BigDecimal.ZERO;
    }

    // 判断库存是否足够
    private boolean checkStorageIsEnough(LeaseOutDetails record) {
        if (record.getManageType().equals(MaTypeManageTypeEnum.NUMBER_DEVICE.getTypeId())) {
            LeaseApplyDetails details = leaseApplyDetailsMapper.getOutboundNum(record);
            if (details == null) {
                return false;
            }
        } else if (record.getManageType().equals(MaTypeManageTypeEnum.CODE_DEVICE.getTypeId())) {
            if (!(Objects.equals(0L, record.getMaId()) || record.getMaId() == null)) {
                String status = machineMapper.getMachineStatus(record);
                return String.valueOf(MaMachineStatusEnum.IN_STORE.getStatus()).equals(status);
            }
        }
        return true;
    }

    private int updateTaskStatus(LeaseOutDetails record) {
        int res;
        // 领用任务单独判断
        if (StringUtils.isNotBlank(record.getPublishTask())) {
            return GlobalConstants.INT_1;
        }
        // 进行状态判断
        List<LeaseApplyDetails> leaseApplyDetailsList = leaseApplyDetailsMapper.getByParentId(record.getParentId());
        int i = GlobalConstants.INT_0;
        for (LeaseApplyDetails bean : leaseApplyDetailsList) {
            if (Objects.equals(bean.getPreNum(), bean.getAlNum())) {
                i++;
            }
        }
        String taskId = leaseApplyInfoMapper.getTaskId(record.getParentId());
        if (i == leaseApplyDetailsList.size()) {
            tmTaskMapper.updateTaskStatus(taskId, LeaseTaskStatusEnum.LEASE_TASK_FINISHED.getStatus());
            res = GlobalConstants.INT_1;
        } else {
            tmTaskMapper.updateTaskStatus(taskId, LeaseTaskStatusEnum.LEASE_TASK_IN_PROGRESS.getStatus());
            res = GlobalConstants.INT_1;
        }
        return res;
    }

    private int checkStorageNum(LeaseOutDetails record) {
        BigDecimal outNum = BigDecimal.valueOf(GlobalConstants.INT_0);
        if (StringUtils.isNull(record)) {
            return GlobalConstants.INT_0;
        }

        if (record.getOutNum() == null) {
            record.setOutNum(BigDecimal.valueOf(0L));
        }
        //判断(ma_type 设备规格表)中的库存够不够出库的
        Type maType = typeMapper.selectByTypeId(record);
        if (maType != null) {
            if ("0".equals(maType.getManageType())) {
                int count = typeMapper.getCountOfCodeMachine(record);
                if (BigDecimal.valueOf(count).compareTo(record.getOutNum()) < GlobalConstants.INT_0) {
                    return GlobalConstants.INT_0;
                }
            } else if ("1".equals(maType.getManageType())) {
                if (maType.getStorageNum() == null || maType.getStorageNum().compareTo(record.getOutNum()) < GlobalConstants.INT_0) {
                    return GlobalConstants.INT_0;
                }
            }
        }
        return GlobalConstants.INT_1;
    }

    private int insertRecords(LeaseOutDetails record) {
        int res = GlobalConstants.INT_0;
        LeaseApplyDetails leaseApplyDetails = new LeaseApplyDetails();
        // 首先更新领料任务详情表的领料数及状态（lease_apply_details）
        if (StringUtils.isNotBlank(record.getPublishTask())) {
            // 领用
            List<LeaseApplyDetails> allList = leaseApplyDetailsMapper.getLeasePublishApplyDetails(record);
            // 出库数量
            BigDecimal outNum = record.getOutNum();
            if (!CollectionUtils.isEmpty(allList)) {
                for (LeaseApplyDetails bean : allList) {
                    bean.setAlNum(outNum);
                    // 剩余出库数量
                    BigDecimal num = bean.getOutNum();
                    if (outNum.compareTo(num) == 0) {
                        res = leaseApplyDetailsMapper.updateLeaseApplyPublishDetailsOutNum(bean);
                        break;
                    } else if (outNum.compareTo(num) > 0) {
                        outNum = outNum.subtract(num);
                        bean.setAlNum(bean.getOutNum());
                        leaseApplyDetailsMapper.updateLeaseApplyPublishDetailsOutNum(bean);
                    } else {
                        res = leaseApplyDetailsMapper.updateLeaseApplyPublishDetails(bean);
                        break;
                    }
                }
            }
            leaseApplyDetails = leaseApplyDetailsMapper.getLeasePublishApply(record);
        } else {
            // 领料办理
            res = leaseApplyDetailsMapper.updateLeaseApplyDetailsOutNum(record);
            leaseApplyDetails = leaseApplyDetailsMapper.getLeaseApplyDetails(record);
        }
        if (leaseApplyDetails.getPreNum().equals(leaseApplyDetails.getAlNum()) || leaseApplyDetails.getAuditNum().equals(leaseApplyDetails.getAlNum())) {
            leaseApplyDetailsMapper.updateLeaseApplyDetailsByLeaseOutRecord(record);
        }
        if (res > GlobalConstants.INT_0) {
            Type type = new Type();
            // 插入领料出库明细表（lease_out_details）
            record.setCreateBy(SecurityUtils.getLoginUser().getUserid().toString());
            res = leaseOutDetailsMapper.insertLeaseOutDetails(record);
            type.setOutNum(record.getOutNum());
            if (res > GlobalConstants.INT_0) {
                if (record.getMaId() !=  null) {
                    if (record.getJiJuType() == GlobalConstants.INT_1) {
                        record.setThisCheckTime(DateUtils.getNowDate());
                        LocalDate currentDate = LocalDate.now();
                         // 计算下一次检验日期：当前日期加一年减一天
                        LocalDate nextCheckDate = currentDate.plusYears(GlobalConstants.INT_1).minusDays(GlobalConstants.INT_1);
                        record.setNextCheckTime(DateUtils.toDate(nextCheckDate));
                    }
                    // 更新 (ma_machine 设备表)的状态
                    res = machineMapper.updateMaMachineStatus(record, MaMachineStatusEnum.IN_USE.getStatus());
                    type.setOutNum(BigDecimal.valueOf(GlobalConstants.INT_1));
                    type.setMaId(record.getMaId());
                }
                type.setTypeId(record.getTypeId());
                type.setStyle("1");
                type.setModelTitle("领料出库");
                type.setCode(record.getCode());
                res = typeService.updateNumAddOrSubtract(type);
            }
        }
        return res;
    }

    /**
     * 插入结算信息
     * @param taskId 任务id
     * @param record 出库记录
     */
    public int insSltInfo(String taskId, LeaseOutDetails record) {
        int res = GlobalConstants.INT_0;
        // 根据发布批次查询结算协议信息
        SltAgreementInfo sltAgreementInfo;
        // 判断是否是班组领用
        sltAgreementInfo = sltAgreementInfoMapper.getSltAgreementInfo(record);
        if (sltAgreementInfo != null) {
            BigDecimal num = sltAgreementInfo.getNum();
            BigDecimal outNum = record.getOutNum();
            sltAgreementInfo.setNum(num.add(outNum));
            res = sltAgreementInfoMapper.updSltInfo(sltAgreementInfo);
            if (!record.getLeaseUnitIsTeam()) {
                record.setAgreementId(sltAgreementInfo.getAgreementId());
            }
        } else {
            String agreementId = tmTaskAgreementMapper.getAgreementId(taskId);
            // 根据发布批次，查询协议ID🆔
            if (StringUtils.isNotBlank(record.getPublishTask())) {
                agreementId = tmTaskAgreementMapper.selectAgreementId(record.getPublishTask());
            }
            if (record.getLeaseUnitIsTeam()) {
                agreementId = String.valueOf(record.getProjectUnitAgreementId());
            }
            // 查询单位类型：内部单位/外部单位
            String protocol = bmAgreementInfoMapper.getProtocol(agreementId);
            Type maType = typeMapper.getMaType(record.getTypeId());
            if (StringUtils.isEmpty(protocol)) {
                maType.setFinalPrice(maType.getLeasePrice());
            } else {
                if (MaterialConstants.INNER_PROTOCAL.equals(protocol)) {
                    maType.setFinalPrice(maType.getLeasePrice());
                } else if (MaterialConstants.OUTER_PROTOCAL.equals(protocol)) {
                    maType.setFinalPrice(maType.getRentPrice());
                } else {
                    maType.setFinalPrice(maType.getLeasePrice());
                }
            }
            res = sltAgreementInfoMapper.insSltInfo(record, agreementId, maType);
            if (!record.getLeaseUnitIsTeam()) {
                record.setAgreementId(Long.valueOf(agreementId));
            }
        }
        return res;
    }

}
