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

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.bonus.common.biz.constant.GlobalConstants;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.domain.lease.LeaseOutDetails;
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.domain.vo.MaCodeVo;
import com.bonus.common.biz.domain.repair.RePairDto;
import com.bonus.material.back.mapper.BackApplyInfoMapper;
import com.bonus.material.basic.domain.BmQrcodeInfo;
import com.bonus.material.input.domain.InputApplyDetails;
import com.bonus.material.lease.mapper.LeaseOutDetailsMapper;
import com.bonus.material.ma.domain.Machine;
import com.bonus.material.ma.domain.Type;
import com.bonus.material.ma.mapper.MachineMapper;
import com.bonus.material.ma.service.ITypeService;
import com.bonus.material.repair.domain.RepairInputInfo;
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 org.springframework.stereotype.Service;
import com.bonus.material.repair.mapper.RepairInputDetailsMapper;
import com.bonus.common.biz.domain.repair.RepairInputDetails;
import com.bonus.material.repair.service.IRepairInputDetailsService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 修试后入库Service业务层处理
 *
 * @author xsheng
 * @date 2024-10-16
 */
@Service
public class RepairInputDetailsServiceImpl implements IRepairInputDetailsService {
    @Resource
    private RepairInputDetailsMapper repairInputDetailsMapper;

    @Resource
    private TmTaskMapper taskMapper;

    @Resource
    private TmTaskAgreementMapper taskAgreementMapper;

    @Resource
    private LeaseOutDetailsMapper leaseOutDetailsMapper;

    @Resource
    private MachineMapper machineMapper;

    @Resource
    private BackApplyInfoMapper backApplyInfoMapper;

    @Resource
    private ITypeService typeService;
    /**
     * 查询修试后入库
     *
     * @param repairInputDetails 修试后入库主键
     * @return 修试后入库
     */
    @Override
    public List<RepairInputInfo> selectRepairInputDetailsById(RepairInputDetails repairInputDetails) {
        Long userId = SecurityUtils.getLoginUser().getUserid();
        // 首先根据用户名去ma_type_manage表查询是否存在绑定物资信息
        /*List<Long> typeIdList = backApplyInfoMapper.selectTypeIdList(userId);
        if (org.springframework.util.CollectionUtils.isEmpty(typeIdList)) {
            repairInputDetails.setUserId(userId == 0 ? null : userId);
        }*/
        Set<String> userRoles = SecurityUtils.getLoginUser().getRoles();
        // 检查用户是否具有特殊角色
        boolean hasSpecialRole = hasSpecialRole(userRoles);
        if (!hasSpecialRole) {
            repairInputDetails.setUserId(userId == 0 ? null : userId);
        }
        List<RepairInputInfo> inputInfos = repairInputDetailsMapper.selectRepairInputDetailsById(repairInputDetails);
        if (CollectionUtils.isNotEmpty(inputInfos)) {
            for (RepairInputInfo inputInfo : inputInfos) {
                RepairInputDetails inputDetails = new RepairInputDetails();
                inputDetails.setTaskId(inputInfo.getTaskId());
                inputDetails.setTypeId(inputInfo.getTypeId());
                List<RepairInputInfo> list = repairInputDetailsMapper.selectRepairDetailsById(inputDetails);
                if (CollectionUtils.isNotEmpty(list)) {
                    List<Integer> statusList = list.stream()
                            .map(info -> Integer.parseInt(info.getStatus()))
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(statusList)) {
                        if (!statusList.contains(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatus()) &&
                                statusList.contains(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus())) {
                            inputInfo.setStatus(String.valueOf(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus()));
                            inputInfo.setStatusName(String.valueOf(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatusName()));
                        } else if (!statusList.contains(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatus()) &&
                                !statusList.contains(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus()) &&
                                statusList.stream().allMatch(status -> status.equals(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus()))) {
                            inputInfo.setStatus(String.valueOf(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus()));
                            inputInfo.setStatusName(String.valueOf(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatusName()));
                        } else {
                            inputInfo.setStatus(String.valueOf(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatus()));
                            inputInfo.setStatusName(String.valueOf(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatusName()));
                        }
                    }
                }
            }
        }
        return inputInfos;
    }

    /**
     * 查询修试后入库列表
     *
     * @param repairInputDetails 修试后入库
     * @return 修试后入库
     */
    @Override
    public List<RepairInputDetails> selectRepairInputDetailsList(RepairInputDetails repairInputDetails) {
        Long userId = SecurityUtils.getLoginUser().getUserid();
        // 首先根据用户名去ma_type_manage表查询是否存在绑定物资信息
       /* List<Long> typeIdList = backApplyInfoMapper.selectTypeIdList(userId);
        if (org.springframework.util.CollectionUtils.isEmpty(typeIdList)) {
            repairInputDetails.setUserId(userId == 0 ? null : userId);
        }*/
        Set<String> userRoles = SecurityUtils.getLoginUser().getRoles();
        // 检查用户是否具有特殊角色
        boolean hasSpecialRole = hasSpecialRole(userRoles);
        if (!hasSpecialRole) {
            repairInputDetails.setUserId(userId == 0 ? null : userId);
        }
        List<RepairInputDetails> list = repairInputDetailsMapper.selectRepairInputDetailsList(repairInputDetails);
        if (CollectionUtils.isNotEmpty(list)) {
            for (RepairInputDetails inputDetails : list) {
               // 根据taskId和userId查询详情，赋值最外层任务状态
                inputDetails.setUserId(SecurityUtils.getLoginUser().getUserid());
                List<String> taskStatusList = repairInputDetailsMapper.selectStatusByTaskId(inputDetails);
                List<Integer> statusList = taskStatusList.stream().map(Integer::parseInt).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(statusList)) {
                    if (!statusList.contains(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatus()) &&
                            statusList.contains(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus())) {
                        inputDetails.setTaskStatus(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus());
                        inputDetails.setStatusName(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatusName());
                    } else if (!statusList.contains(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatus()) &&
                            !statusList.contains(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus()) &&
                            statusList.stream().allMatch(status -> status.equals(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus()))) {
                        inputDetails.setTaskStatus(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus());
                        inputDetails.setStatusName(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatusName());
                    }
                }
            }
        }
            String keyWord = repairInputDetails.getKeyWord();
                    // 如果关键字不为空，进行过滤
        if (!StringUtils.isBlank(keyWord)) {
            list = list.stream()
                    .filter(item -> containsKeyword(item, keyWord))
                    .collect(Collectors.toList());
        }
        if (repairInputDetails.getTaskStatus() != null) {
            list = list.stream()
                    .filter(item -> item.getTaskStatus().equals(repairInputDetails.getTaskStatus()))
                    .collect(Collectors.toList());
        }
        if (repairInputDetails.getAppTaskStatus() != null && repairInputDetails.getAppTaskStatus() == 0) {
            list = list.stream()
                    .filter(item -> item.getTaskStatus().equals(repairInputDetails.getAppTaskStatus()))
                    .collect(Collectors.toList());
        }
        if (repairInputDetails.getAppTaskStatus() != null && repairInputDetails.getAppTaskStatus() == 1) {
            list = list.stream()
                    .filter(item -> item.getTaskStatus() == 1 || item.getTaskStatus() == 2)
                    .collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 检查用户是否具有特殊角色
     * @param userRoles
     * @return
     */
    private boolean hasSpecialRole(Set<String> userRoles) {
        if (userRoles == null) {
            return false;
        }
        List<String> allowedRoles = GlobalConstants.allowedRoles;
        return allowedRoles.stream().anyMatch(userRoles::contains);
    }

    /**
     * 关键字搜索
     * @param item
     * @param keyWord
     * @return
     */
    private boolean containsKeyword(RepairInputDetails item, String keyWord) {
        return (item.getMaterialType() != null && item.getMaterialType().contains(keyWord)) ||
                (item.getRepairCode() != null && item.getRepairCode().contains(keyWord)) ||
                (item.getInputCode() != null && item.getInputCode().contains(keyWord)) ||
                (item.getBackUnit() != null && item.getBackUnit().contains(keyWord)) ||
                (item.getBackPro() != null && item.getBackPro().contains(keyWord)) ||
                (item.getCreateBy() != null && item.getCreateBy().contains(keyWord));
    }

    /**
     * 新增修试后入库
     *
     * @param repairInputDetails 修试后入库
     * @return 结果
     */
    @Override
    public int insertRepairInputDetails(RepairInputDetails repairInputDetails) {
        repairInputDetails.setCreateTime(DateUtils.getNowDate());
        try {
            return repairInputDetailsMapper.insertRepairInputDetails(repairInputDetails);
        } catch (Exception e) {
            throw new ServiceException("错误信息描述");
        }
    }

    /**
     * 修改修试后入库
     *
     * @param repairInputDetails 修试后入库
     * @return 结果
     */
    @Override
    public int updateRepairInputDetails(RepairInputDetails repairInputDetails) {
        repairInputDetails.setUpdateTime(DateUtils.getNowDate());
        try {
            return repairInputDetailsMapper.updateRepairInputDetails(repairInputDetails);
        } catch (Exception e) {
            throw new ServiceException("错误信息描述");
        }
    }

    /**
     * 批量删除修试后入库
     *
     * @param ids 需要删除的修试后入库主键
     * @return 结果
     */
    @Override
    public int deleteRepairInputDetailsByIds(Long[] ids) {
        return repairInputDetailsMapper.deleteRepairInputDetailsByIds(ids);
    }

    /**
     * 删除修试后入库信息
     *
     * @param id 修试后入库主键
     * @return 结果
     */
    @Override
    public int deleteRepairInputDetailsById(Long id) {
        return repairInputDetailsMapper.deleteRepairInputDetailsById(id);
    }

    /**
     * 入库或批量入库操作
     * @param repairInputDetails
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult warehouse(RepairInputDetails repairInputDetails) {
        int result = 0;

        // 检查条件，确保修试入库条件有效
        if (repairInputDetails.getTaskId() != null && repairInputDetails.getTypeId() != null && CollectionUtils.isEmpty(repairInputDetails.getOutTaskList())) {
            // 内层入库
            result += processInnerStorage(repairInputDetails);
        } else if (CollectionUtils.isNotEmpty(repairInputDetails.getOutTaskList())) {
            // 查询外层任务列表，仅供库存日志使用
            List<Long> taskIdList = repairInputDetails.getOutTaskList().stream()
                    .map(RePairDto::getTaskId)
                    .collect(Collectors.toList());
            List<RepairInputDetails> list = repairInputDetailsMapper.selectRepairDetails(taskIdList);
            if (CollectionUtils.isNotEmpty(list)) {
                for (RepairInputDetails inputDetails : list) {
                    inputDetails.setPreStoreNum(getStorageNum(inputDetails));
                }
            }
            repairInputDetails.setDetailsList(list);
            // 外层入库
            result += processOuterStorage(repairInputDetails);
        }

        if (result > 0) {
            return AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg());
        }
        return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 获取编码列表
     * @param mdCodeVo
     * @return
     */
    @Override
    public AjaxResult getCodeList(MaCodeVo mdCodeVo) {
        List<MaCodeVo> list = repairInputDetailsMapper.getCodeList(mdCodeVo);
        return AjaxResult.success(list);
    }

    /**
     * 修试入库驳回或批量驳回
     * @param repairInputDetails
     * @return
     */
    @Override
    public AjaxResult reject(RepairInputDetails repairInputDetails) {
        int result = 0;
        // 检查条件，确保修试驳回条件有效
        if (repairInputDetails.getTaskId() != null && repairInputDetails.getTypeId() != null && CollectionUtils.isEmpty(repairInputDetails.getOutTaskList())) {
            // 内层驳回
            result += processInnerReject(repairInputDetails);
        } else if (CollectionUtils.isNotEmpty(repairInputDetails.getOutTaskList())) {
            // 外层驳回
            result += processOuterReject(repairInputDetails);
        }

        if (result > 0) {
            return AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg());
        }
        return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 获取二维码信息
     * @param bmQrcodeInfo
     * @return
     */
    @Override
    public AjaxResult getInfoByQrcode(BmQrcodeInfo bmQrcodeInfo) {
        if (bmQrcodeInfo.getQrCode() == null && bmQrcodeInfo.getMaCode() == null) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "编码或二维码code不能为空");
        }
        List<RepairInputDetails> recordList = repairInputDetailsMapper.getInfoByQrcode(bmQrcodeInfo);
        if (CollectionUtil.isNotEmpty(recordList)) {
            return AjaxResult.success(recordList);
        }
        return AjaxResult.error(HttpCodeEnum.SYSTEM_ERROR.getCode(), "该编码处于非修试待入库状态");
    }

    /**
     * 外部驳回
     * @param repairInputDetails
     * @return
     */
    private int processOuterReject(RepairInputDetails repairInputDetails) {
        int result = 0;
        for (RePairDto rePairDto : repairInputDetails.getOutTaskList()) {
            result += processRepairRejectTask(rePairDto);
        }
        return result;
    }

    /**
     * 外部驳回
     * @param rePairDto
     * @return
     */
    private int processRepairRejectTask(RePairDto rePairDto) {
        int result = 0;
        RepairInputDetails repairInputDetails1 = new RepairInputDetails();
        repairInputDetails1.setTaskId(rePairDto.getTaskId());
        repairInputDetails1.setAgreementId(rePairDto.getAgreementId());
        List<RepairInputInfo> list = repairInputDetailsMapper.selectRepairDetailsById(repairInputDetails1);
        //根据任务id查询退料id
        Long backId = repairInputDetailsMapper.selectBackIdByTaskId(rePairDto.getTaskId());

        if (CollectionUtils.isNotEmpty(list)) {
            //插入任务表
            Long newTaskId = insertTt(rePairDto.getTaskId());
            result += insertTta(newTaskId, repairInputDetails1);
            for (RepairInputInfo repairInputInfo : list) {
                if (repairInputInfo.getStatus().equals(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus().toString())
                        || repairInputInfo.getStatus().equals(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus().toString())
                ) {
                    continue;
                }
                result += updateRepairRejectDetails(repairInputInfo);
                //插入协议表
                repairInputDetails1.setTypeId(repairInputInfo.getTypeId());
                repairInputDetails1.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
                repairInputDetails1.setTaskId(newTaskId);
                repairInputDetails1.setMaId(repairInputInfo.getMaId());
                repairInputDetails1.setRejectNum(repairInputInfo.getPendingInputNum());
                repairInputDetails1.setBackId(backId);
                result += insertWxTask(newTaskId, repairInputDetails1);
            }
            if (result > 0) {
                result += taskMapper.updateTaskStatus(rePairDto.getTaskId().toString(), RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus());
            }
        }

        return result;
    }

    /**
     * 更新状态为已驳回
     * @param repairInputInfo
     * @return
     */
    private int updateRepairRejectDetails(RepairInputInfo repairInputInfo) {
        int result = 0;
        RepairInputDetails inputDetails = new RepairInputDetails();
        inputDetails.setStatus(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus().toString());
        inputDetails.setRejectNum(repairInputInfo.getPendingInputNum());
        inputDetails.setMaId(repairInputInfo.getMaId() == null ? null : repairInputInfo.getMaId());
        inputDetails.setTaskId(repairInputInfo.getTaskId());
        inputDetails.setTypeId(repairInputInfo.getTypeId());
        inputDetails.setUpdateBy(SecurityUtils.getLoginUser().getUserid().toString());
        inputDetails.setUpdateTime(DateUtils.getNowDate());
        inputDetails.setAuditBy(SecurityUtils.getLoginUser().getUserid());
        inputDetails.setAuditTime(DateUtils.getNowDate());
        result += repairInputDetailsMapper.updateRepairInputDetails(inputDetails);

        if ("0".equals(repairInputInfo.getManageType())) {
            repairInputInfo.setStatus(MaMachineStatusEnum.BACK_REPAIR.getStatus().toString());
            result += repairInputDetailsMapper.updateMaStatus(repairInputInfo);
        }
        return result;
    }

    /**
     * 内部驳回
     * @param repairInputDetails
     * @return
     */
    private int processInnerReject(RepairInputDetails repairInputDetails) {
        int result = 0;
        // 入库数量不能大于预入库数量
        if (repairInputDetails.getRejectNum() != null && repairInputDetails.getPendingInputNum() != null) {
            if (repairInputDetails.getRejectNum().compareTo(repairInputDetails.getPendingInputNum()) > 0) {
                throw new ServiceException("驳回数量不能大于待入库数量");
            }
        }
        //根据任务id查询退料id
        Long backId = repairInputDetailsMapper.selectBackIdByTaskId(repairInputDetails.getTaskId());
        repairInputDetails.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        repairInputDetails.setUpdateBy(SecurityUtils.getLoginUser().getUserid().toString());
        repairInputDetails.setUpdateTime(DateUtils.getNowDate());
        repairInputDetails.setBackId(backId);
        // 编码类型驳回
        if (CollectionUtils.isNotEmpty(repairInputDetails.getMaCodeList())) {
            result += processCodeTypeReject(repairInputDetails);
        } else {
            // 数量类型驳回
            result += processQuantityTypeReject(repairInputDetails);
        }

        return result;
    }

    /**
     * 编码类型驳回
     * @param repairInputDetails
     * @return
     */
    private int processCodeTypeReject(RepairInputDetails repairInputDetails) {
        int result = 0;
        //插入任务表
        Long newTaskId = insertTt(repairInputDetails.getTaskId());
        result += insertTta(newTaskId, repairInputDetails);
        for (RepairInputDetails inputDetails : repairInputDetails.getMaCodeList()) {
            inputDetails.setStatus(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus().toString());
            inputDetails.setTaskId(repairInputDetails.getTaskId());
            inputDetails.setTypeId(repairInputDetails.getTypeId());
            inputDetails.setRejectNum(BigDecimal.valueOf(1));
            inputDetails.setUpdateBy(SecurityUtils.getLoginUser().getUserid().toString());
            inputDetails.setUpdateTime(DateUtils.getNowDate());
            inputDetails.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
            inputDetails.setRejectReason(repairInputDetails.getRejectReason());
            inputDetails.setBackId(repairInputDetails.getBackId());
            inputDetails.setAuditBy(SecurityUtils.getLoginUser().getUserid());
            inputDetails.setAuditTime(DateUtils.getNowDate());
            result += repairInputDetailsMapper.updateRepairInputDetails(inputDetails);
            inputDetails.setStatus(MaMachineStatusEnum.BACK_REPAIR.getStatus().toString());
            updateRepairInputInfo(inputDetails);
            result += insertWxTask(newTaskId, inputDetails);
        }
        if (result > 0) {
            updateTaskStatus(repairInputDetails);
        }
        return result;
    }

    /**
     * 数量类型驳回
     * @param repairInputDetails
     * @return
     */
    private int processQuantityTypeReject(RepairInputDetails repairInputDetails) {
        int result = 0;
        repairInputDetails.setStatus(repairInputDetails.getRejectNum().equals(repairInputDetails.getPendingInputNum()) ? "2" : "0");
        repairInputDetails.setAuditBy(SecurityUtils.getLoginUser().getUserid());
        repairInputDetails.setAuditTime(DateUtils.getNowDate());
        result += repairInputDetailsMapper.updateRepairInputDetails(repairInputDetails);
        if (result > 0) {
            updateTaskStatus(repairInputDetails);
            RepairInputInfo repairInputInfo = new RepairInputInfo();
            repairInputInfo.setTypeId(repairInputDetails.getTypeId());
            repairInputInfo.setInputNum(repairInputDetails.getInputNum());
//            repairInputDetailsMapper.updateNum(repairInputInfo);
            Long newTaskId = insertTt(repairInputDetails.getTaskId());
            result += insertTta(newTaskId, repairInputDetails);
            result += insertWxTask(newTaskId, repairInputDetails);
        }
        return result;
    }

    /**
     * 插入维修工单表
     * @param newTaskId
     * @param repairInputDetails
     * @return
     */
    private int insertWxTask(Long newTaskId, RepairInputDetails repairInputDetails) {
        repairInputDetails.setTaskId(newTaskId);
        return repairInputDetailsMapper.insertRad(repairInputDetails);
    }

    /**
     * 插入协议任务表
     * @param newTaskId
     * @param repairInputDetails
     * @return
     */
    private int insertTta(Long newTaskId, RepairInputDetails repairInputDetails) {
        int res;
        String agreementId = String.valueOf(repairInputDetails.getAgreementId());
        TmTaskAgreement tmTaskAgreement = new TmTaskAgreement(newTaskId, Long.parseLong(agreementId));
        tmTaskAgreement.setCreateTime(DateUtils.getNowDate());
        tmTaskAgreement.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        res = taskAgreementMapper.insertTmTaskAgreement(tmTaskAgreement);
        return res;
    }

    /**
     * 驳回后重新生成维修单 插入任务表
     * @return
     */
    private Long insertTt(Long preTaskId) {
        Long newTask = null;
        int thisMonthMaxOrder = taskMapper.getMonthMaxOrderByDate(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth(), TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId());
        // 生成维修单号
        String code = genderWxTaskCode(thisMonthMaxOrder);
        TmTask tmTask = new TmTask(null, TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId(), BackTaskStatusEnum.BACK_TASK_NO_FINISHED.getStatus(),
                null,thisMonthMaxOrder + 1, code);
        tmTask.setCreateTime(DateUtils.getNowDate());
        tmTask.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        tmTask.setPreTaskId(preTaskId);
        // 插入任务
        int taskId = taskMapper.insertTmTask(tmTask);
        // 如果插入成功且返回的 taskId 大于 0
        if (taskId > 0 && tmTask.getTaskId() > 0) {
            newTask = tmTask.getTaskId();
        }
        return newTask;
    }

    /**
     * 生成维修单号
     * @param thisMonthMaxOrder
     * @return
     */
    private String genderWxTaskCode(int thisMonthMaxOrder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        String result = format.replace("-", "");
        return MaterialConstants.REPAIR_TASK_TYPE_LABEL + result + String.format("-%03d", thisMonthMaxOrder + 1);
    }

    /**
     * 内部入库
     * @param repairInputDetails
     * @return
     */
    private int processInnerStorage(RepairInputDetails repairInputDetails) {
        int result = 0;
        // 获取操作前的库存数量
        repairInputDetails.setPreStoreNum(getStorageNum(repairInputDetails));
        // 入库数量不能大于预入库数量
        if (repairInputDetails.getInputNum() != null && repairInputDetails.getPendingInputNum() != null) {
            if (repairInputDetails.getInputNum().compareTo(repairInputDetails.getPendingInputNum()) > 0) {
                throw new ServiceException("入库数量不能大于预入库数量");
            }
        }
        repairInputDetails.setUpdateBy(SecurityUtils.getLoginUser().getUserid().toString());
        repairInputDetails.setUpdateTime(DateUtils.getNowDate());

        // 编码类型入库
        if (CollectionUtils.isNotEmpty(repairInputDetails.getMaCodeList())) {
            for (RepairInputDetails inputDetails : repairInputDetails.getMaCodeList()) {
                inputDetails.setTaskId(repairInputDetails.getTaskId());
                inputDetails.setTypeId(repairInputDetails.getTypeId());
                // 根据taskId以及typeId查询该设备是否已经入库
                RepairInputDetails info = repairInputDetailsMapper.selectInfoNum(inputDetails);
                if (info != null) {
                    if (info.getInputNum().compareTo(info.getRepairNum()) >= 0) {
                        throw new ServiceException("该设备已经入库,请勿重复入库");
                    }
                }
            }
            result += processCodeTypeStorage(repairInputDetails);
        } else {
            // 根据taskId以及typeId查询该设备是否已经入库
            RepairInputDetails inputDetails = repairInputDetailsMapper.selectInfoNum(repairInputDetails);
            if (inputDetails != null) {
                if (inputDetails.getInputNum().compareTo(inputDetails.getRepairNum()) >= 0) {
                    throw new ServiceException("该设备已经入库,请勿重复入库");
                }
            }
            // 数量类型入库
            result += processQuantityTypeStorage(repairInputDetails);
        }

        return result;
    }

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

    /**
     * 编码类型入库
     * @param repairInputDetails
     * @return
     */
    private int processCodeTypeStorage(RepairInputDetails repairInputDetails) {
        int result = 0;
        for (RepairInputDetails inputDetails : repairInputDetails.getMaCodeList()) {
            inputDetails.setStatus(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus().toString());
            inputDetails.setTaskId(repairInputDetails.getTaskId());
            inputDetails.setTypeId(repairInputDetails.getTypeId());
            inputDetails.setInputNum(BigDecimal.valueOf(1));
            inputDetails.setUpdateBy(SecurityUtils.getLoginUser().getUserid().toString());
            inputDetails.setUpdateTime(DateUtils.getNowDate());
            inputDetails.setAuditBy(SecurityUtils.getLoginUser().getUserid());
            inputDetails.setAuditTime(DateUtils.getNowDate());
            result += repairInputDetailsMapper.updateRepairInputDetails(inputDetails);
            inputDetails.setStatus(MaMachineStatusEnum.IN_STORE.getStatus().toString());
            updateRepairInputInfo(inputDetails);
            Type type = new Type();
            type.setModelTitle("修试入库");
            type.setCode(repairInputDetails.getInputCode());
            type.setTypeId(repairInputDetails.getTypeId());
            type.setStyle("2");
            type.setInputNum(BigDecimal.valueOf(1));
            type.setMaId(inputDetails.getMaId());
            typeService.updateNumAddOrSubtract(type);
        }
        if (result > 0) {
            updateTaskStatus(repairInputDetails);
        }
        return result;
    }

    /**
     * 数量类型入库
     * @param repairInputDetails
     * @return
     */
    private int processQuantityTypeStorage(RepairInputDetails repairInputDetails) {
        int result = 0;
        repairInputDetails.setStatus(repairInputDetails.getInputNum().equals(repairInputDetails.getPendingInputNum()) ? "1" : "0");
        repairInputDetails.setAuditBy(SecurityUtils.getLoginUser().getUserid());
        repairInputDetails.setAuditTime(DateUtils.getNowDate());
        result += repairInputDetailsMapper.updateRepairInputDetails(repairInputDetails);
        if (result > 0) {
            updateTaskStatus(repairInputDetails);
            Type type = new Type();
            type.setModelTitle("修试入库");
            type.setCode(repairInputDetails.getInputCode());
            type.setTypeId(repairInputDetails.getTypeId());
            type.setStyle("2");
            type.setInputNum(repairInputDetails.getInputNum());
            typeService.updateNumAddOrSubtract(type);
        }
        return result;
    }

    /**
     * 更新修试入库信息
     * @param inputDetails
     */
    private void updateRepairInputInfo(RepairInputDetails inputDetails) {
        RepairInputInfo repairInputInfo = new RepairInputInfo();
        repairInputInfo.setMaId(inputDetails.getMaId());
        repairInputInfo.setStatus(inputDetails.getStatus());
        repairInputDetailsMapper.updateMaStatus(repairInputInfo);
    }

    /**
     * 更新修试入库状态
     * @param repairInputDetails
     */
    private void updateTaskStatus(RepairInputDetails repairInputDetails) {
        List<String> list = repairInputDetailsMapper.selectStatusByTaskId(repairInputDetails);
        List<Integer> statusList = list.stream().map(Integer::parseInt).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(statusList)) {
            if (!statusList.contains(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatus()) &&
                    statusList.contains(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus())) {
                taskMapper.updateTaskStatus(repairInputDetails.getTaskId().toString(), RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus());
            } else if (!statusList.contains(RepairInputStatusEnum.INPUT_TASK_NO_FINISHED.getStatus()) &&
                    !statusList.contains(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus()) &&
                    statusList.stream().allMatch(status -> status.equals(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus()))) {
                taskMapper.updateTaskStatus(repairInputDetails.getTaskId().toString(), RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus());
            }
        }
    }

    /**
     * 外部入库
     * @param repairInputDetails
     * @return
     */
    private int processOuterStorage(RepairInputDetails repairInputDetails) {
        int result = 0;
        for (RePairDto rePairDto : repairInputDetails.getOutTaskList()) {
            result += processRepairTask(rePairDto.getTaskId());
        }
        return result;
    }

    /**
     * 修试入库
     * @param taskId
     * @return
     */
    private int processRepairTask(Long taskId) {
        int result = 0;
        RepairInputDetails repairInputDetails1 = new RepairInputDetails();
        repairInputDetails1.setTaskId(taskId);
        List<RepairInputInfo> list = repairInputDetailsMapper.selectRepairDetailsById(repairInputDetails1);

        if (CollectionUtils.isNotEmpty(list)) {
            for (RepairInputInfo repairInputInfo : list) {
                if (repairInputInfo.getStatus().equals(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus().toString())
                        || repairInputInfo.getStatus().equals(RepairInputStatusEnum.INPUT_TASK_TO_REJECT.getStatus().toString())
                ) {
                    continue;
                }
                result += updateRepairInputDetails(repairInputInfo);
            }
            if (result > 0) {
                result += taskMapper.updateTaskStatus(taskId.toString(), RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus());
            }
        }
        return result;
    }

    /**
     * 更新修试入库明细
     * @param repairInputInfo
     * @return
     */
    private int updateRepairInputDetails(RepairInputInfo repairInputInfo) {
        int result = 0;
        RepairInputDetails inputDetails = new RepairInputDetails();
        inputDetails.setStatus(RepairInputStatusEnum.INPUT_TASK_IN_FINISHED.getStatus().toString());
        inputDetails.setInputNum(repairInputInfo.getPendingInputNum());
        inputDetails.setMaId(repairInputInfo.getMaId() == null ? null : repairInputInfo.getMaId());
        inputDetails.setTaskId(repairInputInfo.getTaskId());
        inputDetails.setTypeId(repairInputInfo.getTypeId());
        inputDetails.setAuditBy(SecurityUtils.getLoginUser().getUserid());
        inputDetails.setAuditTime(DateUtils.getNowDate());
        result += repairInputDetailsMapper.updateRepairInputDetails(inputDetails);

        if ("1".equals(repairInputInfo.getManageType())) {
            repairInputInfo.setInputNum(repairInputInfo.getPendingInputNum());
            result += repairInputDetailsMapper.updateNum(repairInputInfo);
        } else if ("0".equals(repairInputInfo.getManageType())) {
            repairInputInfo.setStatus(MaMachineStatusEnum.IN_STORE.getStatus().toString());
            result += repairInputDetailsMapper.updateMaStatus(repairInputInfo);
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int sanInput(RepairInputDetails inputApplyDetails) {
        int  result = 0;
        try  {
            //1查询入参设备是否为待入库设备

            RepairInputDetails inputInfo = new RepairInputDetails();
            if (StringUtils.isNotBlank(inputApplyDetails.getMaCode())) {
                inputInfo = checkCodeMachineStatus(inputApplyDetails.getMaId());
            } else {
                inputInfo = checkMachineStatus(inputApplyDetails.getQrCode());
            }
            if(inputInfo ==null){
                throw new ServiceException("设备不是修试后待入库状态");
            }
            //2更新入库设备数量
            result = updateInputNum(inputInfo);
            if(result <= 0){
                throw new ServiceException("更新入库数量失败");
            }
            //3更新库存数量
            result = updateStorageNum(inputInfo);
            if(result <= 0){
                throw new ServiceException("更新库存数量失败");
            }
            //4更新任务状态
            result = updateRTaskStatus(inputInfo);
            if(result <= 0){
                throw new ServiceException("更新任务状态失败");
            }
        } catch (Exception e) {
            throw new ServiceException("系统错误, " + e.getMessage());
        }

        return result;
    }

    /**
     * 修饰入库之编码入库
     * @param maId
     * @return
     */
    private RepairInputDetails checkCodeMachineStatus(Long maId) {
        InputApplyDetails inputApplyDetails = new InputApplyDetails();
        inputApplyDetails.setMaId(maId);
        return repairInputDetailsMapper.selectInputInfoByMaId(inputApplyDetails);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int sanQrBoxInput(RepairInputDetails repairInputDetails) {
        int  result = 0;
        try  {

            //0查询二维码标准箱绑定的机具
            List<RepairInputDetails> boxList = repairInputDetailsMapper.selectRepairListByBoxId(repairInputDetails);
            //1查询入参设备是否为待入库设备
            for(RepairInputDetails box : boxList){

                RepairInputDetails inputInfo  = checkMachineStatus(box.getQrCode());
                if(inputInfo ==null){
                    throw new ServiceException("设备不是修试后待入库状态");
                }
                //2更新入库设备数量
                result = updateInputNum(inputInfo);
                if(result <= 0){
                    throw new ServiceException("更新入库数量失败");
                }
                //3更新库存数量
                result = updateStorageNum(inputInfo);
                if(result <= 0){
                    throw new ServiceException("更新库存数量失败");
                }
                //4更新任务状态
                result = updateRTaskStatus(inputInfo);
                if(result <= 0){
                    throw new ServiceException("更新任务状态失败");
                }

            }
            //5修改标准箱状态
            result = updateBoxStatus(repairInputDetails);

        } catch (Exception e) {
            throw new ServiceException("系统错误, " + e.getMessage());
        }
        return result;
    }

    private int updateBoxStatus(RepairInputDetails input) {
        int  result = 0;
        result = repairInputDetailsMapper.updateBoxStatus(input);
        return result;
    }

    private int updateRTaskStatus(RepairInputDetails inputApplyDetails) {
        int  result = 0;

        List<RepairInputDetails> inputList = repairInputDetailsMapper.selectInputTaskStatus(inputApplyDetails);

        if(inputList.size() > 0 && inputList!=null){
            result = 1;
        }else{
            result = repairInputDetailsMapper.updateTaskStatus(inputApplyDetails);
        }


        return result;
    }

    /**
     * 修改库存数量
     * @param inputApplyDetails
     * @return
     */
    private int updateStorageNum(RepairInputDetails inputApplyDetails) {
        int  result = 0;
        Type type = new Type();
        type.setModelTitle("修试入库");
        type.setCode(inputApplyDetails.getInputCode());
        type.setTypeId(inputApplyDetails.getTypeId());
        type.setStyle("2");
        type.setInputNum(BigDecimal.valueOf(1));
        type.setMaId(inputApplyDetails.getMaId());
        result = typeService.updateNumAddOrSubtract(type);
        result = machineMapper.updateStatus(inputApplyDetails.getMaId(), 1);
        return result;
    }

    private int updateInputNum(RepairInputDetails inputApplyDetails) {
        int  result = 0;
        Long auditBy = SecurityUtils.getLoginUser().getUserid();
        inputApplyDetails.setAuditBy(auditBy);
        result = repairInputDetailsMapper.updateInputNum(inputApplyDetails);
        return result;
    }

    private RepairInputDetails checkMachineStatus(String qrCode) {
        RepairInputDetails inputInfo = new RepairInputDetails();

        Machine ma = new Machine();
        ma.setQrCode(qrCode);
        Machine ma2 = machineMapper.selectMachineByQrCode(ma);
        long maId = ma2.getMaId();

        String status = ma2.getMaStatus();
        if("5".equals(status)){
            InputApplyDetails inputApplyDetails = new InputApplyDetails();
            inputApplyDetails.setMaId(maId);
            inputInfo = repairInputDetailsMapper.selectInputInfoByMaId(inputApplyDetails);


        }else{
            inputInfo = null;
        }
        return inputInfo;
    }
}
