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

import cn.hutool.core.collection.CollectionUtil;
import com.bonus.common.biz.constant.GlobalConstants;
import com.bonus.common.biz.constant.MaterialConstants;
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.BackApplyInfo;
import com.bonus.material.back.domain.BackCheckDetails;
import com.bonus.material.back.mapper.BackApplyInfoMapper;
import com.bonus.common.biz.domain.BmFileInfo;
import com.bonus.material.back.mapper.BackCheckDetailsMapper;
import com.bonus.material.basic.mapper.BmFileInfoMapper;
import com.bonus.material.ma.domain.PartType;
import com.bonus.material.ma.mapper.MachineMapper;
import com.bonus.material.ma.mapper.PartTypeMapper;
import com.bonus.material.repair.domain.*;
import com.bonus.material.repair.domain.vo.*;
import com.bonus.material.repair.mapper.*;
import com.bonus.material.repair.service.RepairService;
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 com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.util.StringHelper;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author syruan
 */
@Service("RepairService")
@Validated
@Slf4j
public class RepairServiceImpl implements RepairService {

    @Resource
    private RepairMapper repairMapper;

    @Resource
    private TmTaskMapper taskMapper;

    @Resource
    private BmFileInfoMapper bmFileInfoMapper;

    @Resource
    private RepairAuditDetailsMapper repairAuditDetailsMapper;

    @Resource
    private RepairApplyDetailsMapper repairApplyDetailsMapper;

    @Resource
    private BackApplyInfoMapper backApplyInfoMapper;

    @Resource
    private SltAgreementInfoMapper sltAgreementInfoMapper;

    @Resource
    private TmTaskAgreementMapper taskAgreementMapper;

    @Resource
    private PartTypeMapper partTypeMapper;

    @Resource
    private BackCheckDetailsMapper backCheckDetailsMapper;

    @Resource
    private MachineMapper machineMapper;

    @Resource
    private RepairCostMapper repairCostMapper;

    @Resource
    private RepairPartDetailsMapper repairPartDetailsMapper;

    // 1:内部维修   2:外部返厂维修   3:报废
    private final int INNER_REPAIR = 1; // 需要严格匹配枚举值  RepairTypeEnum.INNER_REPAIR.getTypeId();
    private final int RETURN_FACTORY = 2; // 需要严格匹配枚举值  RepairTypeEnum.RETURN_FACTORY.getTypeId();
    private final int TO_SCRAP = 3; // 需要严格匹配枚举值  RepairTypeEnum.TO_SCRAP.getTypeId();

    /**
     * 维修任务一级列表
     *
     * @param bean
     * @return
     */
    @Override
    public List<RepairTask> getRepairTaskList(RepairTask bean) {
        Long userId = SecurityUtils.getLoginUser().getUserid();
        // 首先根据用户名去ma_type_manage表查询是否存在绑定物资信息
        /*List<Long> typeIdList = backApplyInfoMapper.selectTypeIdList(userId);
        if (CollectionUtils.isEmpty(typeIdList)) {
            bean.setUserId(userId == 0 ? null : userId);
        }*/
        Set<String> userRoles = SecurityUtils.getLoginUser().getRoles();
        // 检查用户是否具有特殊角色
        boolean hasSpecialRole = hasSpecialRole(userRoles);
        if (!hasSpecialRole) {
            bean.setUserId(userId == 0 ? null : userId);
        }
        List<RepairTask> list = repairMapper.getRepairTaskList(bean);
        if (CollectionUtil.isNotEmpty(list)) {
            for (RepairTask repairTask : list) {
                // 根据backId查询是否为定损单，需追溯到拆分第一级
                RepairTask task = repairMapper.selectInfo(repairTask);
                if (task != null) {
                    repairTask.setNum(task.getNum());
                }
            }
            /*if (CollectionUtil.isNotEmpty(typeIdList)) {
                // 使用流过滤符合条件的元素
                list = list.stream()
                        .filter(item -> {
                            String firstIdStr = item.getFirstId();
                            if (firstIdStr == null) {
                                return false;
                            }
                            // 将逗号分隔的字符串转为集合
                            Set<Long> firstIds = Arrays.stream(firstIdStr.split(","))
                                    .map(String::trim)
                                    .filter(s -> !s.isEmpty())
                                    .map(Long::parseLong)
                                    .collect(Collectors.toSet());

                            // 判断两个集合是否有交集
                            return firstIds.stream().anyMatch(typeIdList::contains);
                        })
                        .collect(Collectors.toList());
            }*/
            String keyWord = bean.getKeyWord();
            // 如果关键字不为空，进行过滤
            if (!StringUtils.isBlank(keyWord)) {
                list = list.stream()
                        .filter(item -> containsKeyword(item, keyWord))
                        .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(RepairTask item, String keyWord) {
        return (item.getType() != null && item.getType().contains(keyWord)) ||
                (item.getRepairCode() != null && item.getRepairCode().contains(keyWord)) ||
                (item.getBackUnit() != null && item.getBackUnit().contains(keyWord)) ||
                (item.getBackPro() != null && item.getBackPro().contains(keyWord)) ||
                (item.getBackCode() != null && item.getBackCode().contains(keyWord)) ||
                (item.getCreateName() != null && item.getCreateName().contains(keyWord));
    }

    @Override
    public List<RepairTask> exportRepairTaskList(RepairTask bean) {
        return repairMapper.exportRepairTaskList(bean);
    }

    @Override
    public List<RepairDeviceSummaryVo> getRepairDeviceSummary(RepairTaskDetails bean) {
        Long userId = SecurityUtils.getLoginUser().getUserid();
        // 首先根据用户名去ma_type_manage表查询是否存在绑定物资信息
        /*List<Long> typeIdList = backApplyInfoMapper.selectTypeIdList(userId);
        if (CollectionUtils.isEmpty(typeIdList)) {
            bean.setUserId(userId == 0 ? null : userId);
        }*/
        Set<String> userRoles = SecurityUtils.getLoginUser().getRoles();
        // 检查用户是否具有特殊角色
        boolean hasSpecialRole = hasSpecialRole(userRoles);
        if (!hasSpecialRole) {
            bean.setUserId(userId == 0 ? null : userId);
        }
        List<RepairDeviceSummaryVo> repairDeviceSummaryVoList = new ArrayList<>();
        List<RepairDeviceVO> repairDeviceList = repairMapper.getRepairDeviceList(bean);
        /*if (CollectionUtil.isNotEmpty(repairDeviceList)) {
            if (CollectionUtil.isNotEmpty(typeIdList)) {
                repairDeviceList = repairDeviceList.stream()
                        .filter(item -> typeIdList.contains(item.getFirstId()))
                        .collect(Collectors.toList());
            }
        }*/
        Map<Long, List<RepairDeviceVO>> map = repairDeviceList.stream().collect(Collectors.groupingBy(RepairDeviceVO::getTypeId));
        for (Long key : map.keySet()) {
            List<RepairDeviceVO> tempList = map.get(key);
            if (CollectionUtil.isNotEmpty(tempList)) {
                RepairDeviceSummaryVo vo = new RepairDeviceSummaryVo();
                Long[] ids = tempList.stream().map(RepairDeviceVO::getId).toArray(Long[]::new);
                BigDecimal repairNumSum = tempList.stream()
                        .map(RepairDeviceVO::getRepairNum)
                        .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal repairedNumSum = tempList.stream()
                        .map(RepairDeviceVO::getRepairedNum)
                        .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal scrapNumSum = tempList.stream()
                        .map(RepairDeviceVO::getScrapNum)
                        .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal completeNum = tempList.stream()
                        .map(RepairDeviceVO::getCompleteNum)
                        .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                Integer dataStatusSum = tempList.stream()
                        .map(RepairDeviceVO::getDataStatus)
                        .filter(Objects::nonNull)
                        .map(status -> "1".equals(status) ? 1 : 0) // 安全转换
                        .reduce(0, Integer::sum);
                BigDecimal waitRepairNum = repairNumSum.subtract(repairedNumSum).subtract(scrapNumSum);
                BigDecimal typeCostSum = tempList.stream().map(RepairDeviceVO::getTotalCost).reduce(BigDecimal.ZERO, BigDecimal::add);
                vo.setRepairDeviceList(tempList)
                        .setIds(ids).setTypeRepairNum(repairNumSum).setTypeRepairedNum(repairedNumSum)
                        .setTypeScrapNum(scrapNumSum).setTaskId(tempList.get(0).getTaskId())
                        .setCode(tempList.get(0).getCode()).setTypeName(tempList.get(0).getTypeName())
                        .setTypeId(tempList.get(0).getTypeId()).setType(tempList.get(0).getType())
                        .setUnitName(tempList.get(0).getUnitName()).setManageType(tempList.get(0).getManageType())
                        .setDataStatusNum(dataStatusSum)
                        .setUnitValue(tempList.get(0).getUnitValue())
                        .setWaitRepairNum(waitRepairNum)
                        .setCompleteNum(completeNum)
                        .setTypeCost(typeCostSum);
                repairDeviceSummaryVoList.add(vo);
            }
        }
        return repairDeviceSummaryVoList;
    }

//    @Override
//    public List<RepairDeviceListVo> getRepairMaTypeList(RepairTaskDetails bean, boolean isGroup) {
//        if (Objects.isNull(bean)) {
//            return new ArrayList<>();
//        }
//        bean.setCompanyId(null);
//        List<RepairDeviceListVo> repairMaTypeList = repairMapper.getRepairMaTypeList(bean);
//
//        if (repairMaTypeList.isEmpty() || !isGroup) {
//            return repairMaTypeList;
//        }
//        repairMaTypeList.removeIf(Objects::isNull);
//        // 创建Map集合，用于快速分组，使用 ConcurrentHashMap 保证线程安全
//        Map<Long, RepairDeviceListVo> resultMap = new ConcurrentHashMap<>();
//
//        // 遍历处理，把相同的父级对象，拆分到子集合中
//        repairMaTypeList.forEach(item -> {
//            // 创建对象，并复制字段value
//            RepairDeviceVO repairDeviceVO = new RepairDeviceVO();
//            try {
//                BeanUtil.copyProperties(item, repairDeviceVO);
//            } catch (Exception e) {
//                System.err.println("复制属性时发生错误: {}" + e.getMessage());
//                throw new RuntimeException("复制属性时发生错误", e);
//            }
//            if (item.getTypeNameId() == null) {
//                System.err.println("typeNameId 为空，跳过当前项: " + item);
//                return;
//            }
//            resultMap.computeIfAbsent(item.getTypeNameId(), origin -> item).getRepairDeviceList().add(repairDeviceVO);
//
//            resultMap.computeIfPresent(item.getTypeNameId(), (origin, novel) -> {
//                novel.setTotalCost(Optional.ofNullable(novel.getTotalCost()).orElse(BigDecimal.ZERO)
//                        .add(Optional.ofNullable(item.getTotalCost()).orElse(BigDecimal.ZERO))
//                );
//                return novel;
//            });
//        });
//
//        for (Long key : resultMap.keySet()) {
//            RepairDeviceListVo vo = resultMap.get(key);
//            if (MaTypeManageTypeEnum.CODE_DEVICE.getTypeId().equals(vo.getManageType())) {
//                vo.setRepairNum((int) vo.getRepairDeviceList().stream().filter(o -> o.getRepairNum() > 0).count());
//                vo.setRepairedNum((int) vo.getRepairDeviceList().stream().filter(o -> o.getRepairedNum() > 0).count());
//            }
//        }
//
//        return new ArrayList<>(resultMap.values());
//    }

    /**
     * 查询维修单
     *
     * @param taskId 任务id
     */
    @Override
    public AjaxResult getRepairDocumentInfo(Long taskId) {
        try {
            // 查询维修任务信息
            RepairTask repairTaskInfo = repairMapper.getRepairTaskInfoByTaskId(taskId);
            if (Objects.isNull(repairTaskInfo)) {
                return AjaxResult.error("未查询到维修任务信息");
            }
            // 查询维修任务详情
//            List<RepairDeviceListVo> repairMaTypeGroupList = getRepairMaTypeList(new RepairTaskDetails(taskId), true);
//            repairMaTypeGroupList.removeIf(Objects::isNull);
//            repairMaTypeGroupList.forEach(repairDevice -> {
//                List<BmFileInfo> fileInfos = bmFileInfoMapper.selectBmFileInfoList(new BmFileInfo()
//                        .setTaskId(OptionalLong.of(thisTaskId).orElse(0L))
//                        .setModelId(Optional.ofNullable(repairDevice.getId()).orElse(0L))
//                        .setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
//                );
//                repairDevice.setFileList(fileInfos);
//            });

            List<RepairDeviceSummaryVo> repairDeviceSummaryList = getRepairDeviceSummary(new RepairTaskDetails(taskId));
            repairDeviceSummaryList.removeIf(Objects::isNull);
            repairDeviceSummaryList.forEach(repairDevice -> {
                List<BmFileInfo> fileInfos = bmFileInfoMapper.selectBmFileInfoList(new BmFileInfo()
                        .setTaskId(OptionalLong.of(taskId).orElse(0L))
                        .setModelId(Optional.ofNullable(repairDevice.getIds()[0]).orElse(0L))
                        .setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
                );
                repairDevice.setFileList(fileInfos);
            });

            List<RepairPart> repairPartList = repairAuditDetailsMapper.getPartDetailsByTaskId(new RepairAuditDetails().setTaskId(taskId));
            repairPartList = mergePartsNum(repairPartList);
            List<RepairPart> repairPartList2 = repairAuditDetailsMapper.getPartRecordNum(new RepairAuditDetails().setTaskId(taskId));
            if (!repairPartList2.isEmpty()) {
                repairPartList.addAll(repairPartList2);
            }
            RepairTicketVo result = new RepairTicketVo().setRepairTaskInfo(repairTaskInfo)
                    .setRepairDeviceSummaryList(repairDeviceSummaryList)
                    .setRepairPartArray(Optional.of(repairPartList).orElse(Collections.emptyList()));

            return AjaxResult.success(result);
        } catch (NumberFormatException e) {
            return AjaxResult.error("TaskId转换类型时发生错误:" + e.getMessage());
        } catch (DataAccessException e) {
            return AjaxResult.error("数据库查询操作失败:" + e.getMessage());
        } catch (Exception e) {
            return AjaxResult.error("代码处理异常:" + e.getMessage());
        }
    }

    public static List<RepairPart> mergePartsNum(@NotNull List<RepairPart> devices) {
        try {
            Map<String, RepairPart> map = devices.stream().filter(Objects::nonNull).collect(
                    Collectors.toConcurrentMap(device -> device.getTypeId() + ":" + device.getPartCost() + ":" + device.getPartName(),
                            device -> device, (existing, recently) -> {
                                existing.setPartNum(existing.getPartNum() + recently.getPartNum());
                                return existing;
                            }, ConcurrentHashMap::new)
            );
            List<RepairPart> list = new ArrayList<>(map.values());
            list.forEach(item -> item.setPartCost(Optional.ofNullable(item.getPartPrice()).orElse(BigDecimal.ZERO)
                    .multiply(BigDecimal.valueOf(Optional.ofNullable(item.getPartNum()).orElse(0))))
            );
            return list;
        } catch (Exception e) {
            throw new ServiceException("Error merging parts" + e.getMessage());
        }
    }

    /**
     * 提交维修记录
     *
     * @param bean repairApplyRecord
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submitRepairApply(@NotNull(message = "参数不能为空") RepairApplyRecord bean) {
        if (null == bean || null == bean.getRepairType()) {
            return AjaxResult.error("维修方式参数不能为空");
        }

        // 获取维修详情记录：待维修、已维修、报废的数量
        RepairTaskDetails details = repairMapper.getById(bean.getId());
        LoginUser loginUser = SecurityUtils.getLoginUser();
        bean.setCreateBy(String.valueOf(loginUser.getUserid()));

        // 获取维修配件列表
        List<RepairPartDetails> partList = bean.getPartList();
        BigDecimal sfCosts = BigDecimal.ZERO;

        // 收费配件
        String sfPart = "1";

        if (CollectionUtil.isNotEmpty(partList)) {
            bean.setRepairNum(partList.get(0).getRepairNum()).setRepairer(partList.get(0).getRepairer());
        }

        // 根据维修类型，更新维修数量、报废数量
        switch (bean.getRepairType()) {
            case INNER_REPAIR: {
                BigDecimal repairNum = verifyRepairNum(bean, details);
                // 更新维修数量、并修改维修人员
                repairMapper.updateRepairedNum(bean.getId(), repairNum, loginUser.getUserid(), loginUser.getUserid());
                break;
            }
            case RETURN_FACTORY: {
                BigDecimal repairNum = verifyRepairNum(bean, details);
                // 更新维修数量、维修人员不变
                repairMapper.updateRepairedNumTwo(bean.getId(), repairNum, loginUser.getUserid());
                break;
            }
            case TO_SCRAP: {
                BigDecimal scrapNum = details.getScrapNum().add(bean.getScrapNum());
                BigDecimal totalNum = scrapNum.add(details.getRepairedNum());
                if (0 < totalNum.compareTo(details.getRepairNum())) {
                    throw new ServiceException("维修数量大于维修总量");
                }
                // 更新报废数量
                repairMapper.updateScrapNum(bean.getId(), scrapNum, loginUser.getUserid());
                break;
            }
            default:
                break;
        }

        // 判断配件列表是否为空
        if (CollectionUtil.isNotEmpty(partList)) {
            // 内部维修
            if (Objects.equals(RepairTypeEnum.INNER_REPAIR.getTypeId(), bean.getRepairType())) {
                // 遍历配件列表，判断配件类型，收费还是不收费
                for (RepairPartDetails partDetails : partList) {
                    if (null != partDetails.getPartId()) {
                        // 有维修配件时,如果价格为空，设置为0
                        if (null == partDetails.getPartCost()) {
                            partDetails.setPartCost(BigDecimal.ZERO);
                        }
                        partDetails.setTaskId(bean.getTaskId())
                                .setMaId(bean.getMaId())
                                .setTypeId(bean.getTypeId())
                                .setCompanyId(bean.getCompanyId())
                                .setCreateBy(String.valueOf(Optional.ofNullable(loginUser.getUserid()).orElse(0L)));

                        // 根据 partId  找配件单价
                        BigDecimal partPrice = repairMapper.selectPartPrice(partDetails.getPartId());
                        // 设置配件费用
                        partDetails.setPartCost(partPrice);
                        // 添加【维修配件明细表】
                        repairMapper.addPart(partDetails);

                        bean.setPartPrice(partDetails.getPartCost());
                        bean.setPartId((long) partDetails.getPartId().intValue());
                        bean.setPartNum(partDetails.getPartNum());
                        bean.setRepairContent(partDetails.getRepairContent());
                        bean.setPartType(partDetails.getPartType());
                        // 添加【维修记录表】
                        repairMapper.addRecord(bean);
                    } else {
                        // 不选维修配件时, 只添加【维修记录表】
                        repairMapper.addRecord(bean);
                    }
                }
            }

            // 返厂维修
            if (RepairTypeEnum.RETURN_FACTORY.getTypeId().equals(bean.getRepairType())) {
                bean.setPartName(partList.get(0).getPartName());
                bean.setPartType(partList.get(0).getPartType());
                bean.setRepairContent(partList.get(0).getRepairContent());
                if (null == partList.get(0).getSupplierId()) {
                    throw new ServiceException("请选择返厂厂家");
                } else {
                    bean.setSupplierId(partList.get(0).getSupplierId());
                }
                bean.setPartPrice(null == partList.get(0).getPartPrice() ? BigDecimal.ZERO : partList.get(0).getPartPrice());
                bean.setPartNum(partList.get(0).getPartNum());
                // 新增【维修记录表】
                repairMapper.addRecord(bean);
            }
            // 配件费用计算
            sfCosts = countPartCosts(partList, sfCosts);

            // 判断是否是收费配件
            if (Objects.equals(sfPart, sfCosts.toString())) {
                // SQL: 新增【维修费用记录表】
                repairMapper.addRepairCost(bean, sfCosts, sfPart);
            }
        } else {
            // 新增【维修记录表--预报废】
            repairMapper.addRecord(bean);
        }
        return AjaxResult.success();
    }

    /**
     * 校验维修数量
     */
    private static BigDecimal verifyRepairNum(RepairApplyRecord bean, RepairTaskDetails details) {
        if (null == bean || null == bean.getRepairNum()) {
            throw new ServiceException("维修数量不能为空");
        }
        if (null == details.getRepairedNum()) {
            details.setRepairedNum(BigDecimal.ZERO);
        }
        if (null == details.getScrapNum()) {
            details.setScrapNum(BigDecimal.ZERO);
        }
        if (null == details.getRepairNum()) {
            details.setRepairNum(BigDecimal.ZERO);
        }
        BigDecimal repairNum = details.getRepairedNum().add(bean.getRepairNum());

        if (repairNum.add(details.getScrapNum()).compareTo(details.getRepairNum()) > 0) {
            throw new ServiceException("维修数量大于维修总量");
        }
        return repairNum;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult fastRepairApply(List<RepairTaskDetails> list) {
        LoginUser loginUser = SecurityUtils.getLoginUser();

        // 判断待维修数量是否大于0
        for (RepairTaskDetails bean : list) {
            BigDecimal repairedNum = bean.getRepairNum().subtract(bean.getRepairedNum()).subtract(bean.getScrapNum());
            if (repairedNum.compareTo(BigDecimal.ZERO) <= 0) {
                throw new ServiceException("选中的数据中包含待维修数量为0的机具，请重新选择");
            }
        }

        // 执行SQL： 1.增加【维修记录表】、  2.修改【维修明细表】的维修数量
        for (RepairTaskDetails bean : list) {
            BigDecimal repairedNum = bean.getRepairNum().subtract(bean.getRepairedNum()).subtract(bean.getScrapNum());
            RepairApplyRecord repairRecord = new RepairApplyRecord();
            repairRecord.setTaskId(bean.getTaskId());
            repairRecord.setMaId(Long.valueOf(bean.getMaId()));
            repairRecord.setTypeId(Long.valueOf(bean.getTypeId()));
            repairRecord.setRepairNum(repairedNum);
            // 快捷维修，设置为内部维修
            repairRecord.setRepairType(RepairTypeEnum.INNER_REPAIR.getTypeId());
            repairRecord.setCreateBy(String.valueOf(loginUser.getUserid()));
            repairRecord.setCompanyId(bean.getCompanyId());
            repairMapper.addRecord(repairRecord);
            BigDecimal repairNum = repairedNum.add(bean.getRepairedNum());
            repairMapper.updateRepairedNumTwo(bean.getId(), repairNum, loginUser.getUserid());
        }

        // 执行完毕，无异常返回至前端
        return AjaxResult.success();
    }

    @Override
    public AjaxResult batchRepairApply(@NotNull List<RepairDeviceVO> repairDeviceVOList) {
        // 准备业务逻辑数据
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 配件集合
        List<RepairPartDetails> partList;

        // 校验参数，过滤空数据
        repairDeviceVOList.removeIf(Objects::isNull);

        for (RepairDeviceVO bean : repairDeviceVOList) {
            if (null == bean.getManageType()) {
                throw new ServiceException("请选择物资管理方式");
            }
            if (Objects.equals(MaTypeManageTypeEnum.CODE_DEVICE.getTypeId(), bean.getManageType())) {
                partList = bean.getNumberInRepairPartList();
                // 物资管理方式--编码管理
                if (null == bean.getRepairType()) {
                    continue;
                }
                //修改ma_machine表检验信息
                ArrayList<Long> ids = new ArrayList<>();
                ids.add(bean.getId());
                repairMapper.updateMaMachine(ids, SecurityUtils.getLoginUser().getSysUser().getNickName());

                // 根据维修方式，更新维修数量、报废数量
                switch (bean.getRepairType()) {
                    case INNER_REPAIR: {
                        partList = bean.getCodeInRepairPartList();
                        // 更新维修数量、并修改维修人员
                        repairMapper.updateRepairedNumAndStatus(bean.getId(), BigDecimal.ONE, 1, loginUser.getUsername(), loginUser.getUserid());
                        // 保存内部维修文件
                        if (CollectionUtil.isNotEmpty(bean.getInRepairList())) {
                            if (CollectionUtil.isNotEmpty(bean.getInRepairList().get(0).getFileList())) {
                                for (BmFileInfo fileInfo : bean.getInRepairList().get(0).getFileList()) {
                                    fileInfo.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
                                            .setFileType(Long.valueOf(RepairTypeEnum.INNER_REPAIR.getTypeId()))
                                            .setTaskId(bean.getTaskId()).setModelId(bean.getId())
                                            .setCreateBy(loginUser.getSysUser().getNickName());
                                    fileInfo.setCreateTime(DateUtils.getNowDate());
                                    bmFileInfoMapper.insertBmFileInfo(fileInfo);
                                }
                            }
                        }
                        break;
                    }
                    case RETURN_FACTORY: {
                        partList = bean.getCodeOutRepairPartList();
                        // 更新维修数量、维修人员不变
                        repairMapper.updateRepairedNumTwoAndStatus(bean.getId(), BigDecimal.ONE, 1, loginUser.getUserid());
                        // 保存外部维修文件
                        if (CollectionUtil.isNotEmpty(bean.getOutRepairList())) {
                            if (CollectionUtil.isNotEmpty(bean.getOutRepairList().get(0).getFileList())) {
                                for (BmFileInfo fileInfo : bean.getOutRepairList().get(0).getFileList()) {
                                    fileInfo.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
                                            .setFileType(Long.valueOf(RepairTypeEnum.RETURN_FACTORY.getTypeId()))
                                            .setTaskId(bean.getTaskId()).setModelId(bean.getId())
                                            .setCreateBy(loginUser.getSysUser().getNickName());
                                    fileInfo.setCreateTime(DateUtils.getNowDate());
                                    bmFileInfoMapper.insertBmFileInfo(fileInfo);
                                }
                            }
                        }
                        break;
                    }
                    case TO_SCRAP: {
                        // 报废无需上传配件、直接初始化空集合
                        partList = bean.getCodeScrapRepairPartList();
                        // 更新报废数量
                        repairMapper.updateScrapNumAndStatus(bean.getId(), BigDecimal.ONE, 1, loginUser.getUserid());
                        break;
                    }
                    default:
                        System.err.println("请输入正确的维修类型:" + bean.getRepairType());
                        break;
                }

                // 更新维修人员信息
                if (!CollectionUtils.isEmpty(bean.getRepairList())) {
                    RepairPartDetails repairPartDetails = bean.getRepairList().get(0);
                    bean.setRepairer(repairPartDetails.getRepairer());
                    bean.setRemark(repairPartDetails.getRemark());
                    repairMapper.updateRepairer(bean);
                } else {
                    bean.setRepairer(SecurityUtils.getLoginUser().getSysUser().getNickName());
                    repairMapper.updateRepairer(bean);
                }

                // 统一处理配件集合数据
                copeNumberManageInList(bean, partList, loginUser, bean.getManageType());

            } else if (Objects.equals(MaTypeManageTypeEnum.NUMBER_DEVICE.getTypeId(), bean.getManageType())) {
                // 物资管理方式--数量管理
                if (null == bean.getId()) {
                    throw new ServiceException("请完善参数，维修详情ID为空!");
                }
                if (null == bean.getRepairType()) {
                    continue;
                }

                // 更新维修人员信息
                if (!CollectionUtils.isEmpty(bean.getRepairList())) {
                    RepairPartDetails repairPartDetails = bean.getRepairList().get(0);
                    bean.setRepairer(repairPartDetails.getRepairer());
                    bean.setRemark(repairPartDetails.getRemark());
                    repairMapper.updateRepairer(bean);
                    for (RepairPartDetails partDetails : bean.getRepairList()) {
                        if (!CollectionUtils.isEmpty(partDetails.getFileList())) {
                            for (BmFileInfo bmFileInfo : partDetails.getFileList()) {
                                bmFileInfo.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR_NUM.getTaskTypeId())
                                        .setTaskId(bean.getTaskId()).setModelId(bean.getId())
                                        .setCreateBy(loginUser.getSysUser().getNickName());
                                bmFileInfoMapper.insertBmFileInfo(bmFileInfo);
                            }
                        }
                    }
                }
                BigDecimal innerRepairNum = BigDecimal.ZERO;
                BigDecimal outerRepairNum = BigDecimal.ZERO;
                BigDecimal scrapNum = BigDecimal.ZERO;

                // 处理配件--数量管理--内部维修
                if (CollectionUtil.isNotEmpty(bean.getNumberInRepairPartList())) {
                    partList = bean.getNumberInRepairPartList();
                    if (null != partList.get(0).getRepairNum() && 0 < partList.get(0).getRepairNum().compareTo(BigDecimal.ZERO)) {
                        // 获取维修详情表中的维修详情记录：待维修、已维修、已报废的数量
                        RepairTaskDetails details = repairMapper.getById(bean.getId());
                        if (Objects.isNull(details)) {
                            throw new ServiceException("此维修记录不存在，请检查后提交!");
                        }
                        // 分拆维修单, 准备数据
                        innerRepairNum = partList.get(0).getRepairNum();
                        // 处理配件集合数据
                        copeNumberManageInList(bean, partList, loginUser, bean.getManageType());
                    }
                }
                // 保存内部维修文件
                if (CollectionUtil.isNotEmpty(bean.getInRepairList())) {
                    if (CollectionUtil.isNotEmpty(bean.getInRepairList().get(0).getFileList())) {
                        for (BmFileInfo fileInfo : bean.getInRepairList().get(0).getFileList()) {
                            fileInfo.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
                                    .setFileType(Long.valueOf(RepairTypeEnum.INNER_REPAIR.getTypeId()))
                                    .setTaskId(bean.getTaskId()).setModelId(bean.getId())
                                    .setCreateBy(loginUser.getSysUser().getNickName());
                            fileInfo.setCreateTime(DateUtils.getNowDate());
                            bmFileInfoMapper.insertBmFileInfo(fileInfo);
                        }
                    }
                }

                // 处理配件集合数据 -- 数量管理--外部返厂维修
                if (CollectionUtil.isNotEmpty(bean.getNumberOutRepairPartList())) {
                    // 获取维修详情表中的维修详情记录：待维修、已维修、已报废的数量
                    RepairTaskDetails details = repairMapper.getById(bean.getId());
                    if (Objects.isNull(details)) {
                        throw new ServiceException("此维修记录不存在，请检查后提交!");
                    }
                    BigDecimal sfCosts = BigDecimal.ZERO;
                    partList = bean.getNumberOutRepairPartList();
                    // 重新查询维修详情
                    details = repairMapper.getById(bean.getId());

                    // 判断外部维修配件数量是否为空
                    if (null != partList.get(0).getRepairNum() && partList.get(0).getRepairNum().compareTo(BigDecimal.ZERO) > 0) {
                        // 分拆维修单, 准备数据
                        outerRepairNum = partList.get(0).getRepairNum();

                        if (null == partList.get(0).getSupplierId()) {
                            throw new ServiceException("请选择返厂厂家");
                        }

                        // 数量管理--外部返厂维修 -- 记录表插入数据
                        RepairApplyRecord repairApplyRecord = new RepairApplyRecord();
                        for (RepairPartDetails repairPartDetails : partList) {
                            repairApplyRecord.setId(bean.getId()).setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId())
                                    .setRepairType(RepairTypeEnum.RETURN_FACTORY.getTypeId()).setRepairNum(repairPartDetails.getRepairNum()).setScrapNum(BigDecimal.valueOf(0))
                                    .setPartName(repairPartDetails.getPartName()).setPartType(repairPartDetails.getPartType())
                                    .setRepairContent(repairPartDetails.getRepairContent()).setSupplierId(repairPartDetails.getSupplierId())
                                    .setPartNum(repairPartDetails.getPartNum()).setRepairer(loginUser.getUsername())
                                    .setPartPrice(Optional.ofNullable(repairPartDetails.getPartPrice()).orElse(BigDecimal.ZERO))
                                    .setCreateBy(loginUser.getSysUser().getNickName());
                            if (CollectionUtil.isNotEmpty(bean.getOutRepairList())) {
                                repairApplyRecord.setRemark(StringUtils.isNotBlank(bean.getOutRepairList().get(0).getRemark()) ? bean.getOutRepairList().get(0).getRemark() : "");
                            }
                            // 新增【维修记录表】
                            repairMapper.addRecord(repairApplyRecord);
                        }
                        // 保存外部维修文件
                        if (CollectionUtil.isNotEmpty(bean.getOutRepairList())) {
                            if (CollectionUtil.isNotEmpty(bean.getOutRepairList().get(0).getFileList())) {
                                for (BmFileInfo fileInfo : bean.getOutRepairList().get(0).getFileList()) {
                                    fileInfo.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
                                            .setFileType(Long.valueOf(RepairTypeEnum.RETURN_FACTORY.getTypeId()))
                                            .setTaskId(bean.getTaskId()).setModelId(bean.getId())
                                            .setCreateBy(loginUser.getSysUser().getNickName());
                                    fileInfo.setCreateTime(DateUtils.getNowDate());
                                    bmFileInfoMapper.insertBmFileInfo(fileInfo);
                                }
                            }
                        }
                        for (int i = 0; i < partList.size(); i++) {
                            sfCosts = sfCosts.add(partList.get(i).getPartPrice());
                        }
//                        sfCosts = countPartCosts(partList, sfCosts);
                        // TODO: 判断是否是收费配件，因数据存在多条，可能有些是免费配件 有些收费，所以这里用价格统一做处理，后续讨论
                        // SQL: 新增【维修费用记录表】
                        repairMapper.addRepairCost(repairApplyRecord, sfCosts, sfCosts.equals(BigDecimal.ZERO) ? "0" : "1");
                    }
                }

                // 处理配件集合数据 -- 数量管理--报废维修
                if (CollectionUtil.isNotEmpty(bean.getNumberScrapRepairPartList())) {
                    // 判断报废数量是否为空
                    if (bean.getNumberScrapRepairPartList().get(0).getScrapNum() != null && bean.getNumberScrapRepairPartList().get(0).getScrapNum().compareTo(BigDecimal.ZERO) > 0) {
                        // 获取维修详情表中的维修详情记录：待维修、已维修、已报废的数量
                        RepairTaskDetails details = repairMapper.getById(bean.getId());

                        if (Objects.isNull(details)) {
                            throw new ServiceException("此维修记录不存在，请检查后提交!");
                        }

                        // 分拆维修单, 准备数据
                        scrapNum = bean.getNumberScrapRepairPartList().get(0).getScrapNum();

                        if (CollectionUtil.isNotEmpty(bean.getNumberScrapRepairPartList().get(0).getFileList())) {
                            for (BmFileInfo fileInfo : bean.getNumberScrapRepairPartList().get(0).getFileList()) {
                                fileInfo.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
                                        .setFileType(Long.valueOf(RepairTypeEnum.TO_SCRAP.getTypeId()))
                                        .setTaskId(bean.getTaskId()).setModelId(bean.getId())
                                        .setCreateBy(loginUser.getUsername());
                                bmFileInfoMapper.insertBmFileInfo(fileInfo);

                                // 报废类型无需配件，所以配件为空，添加【维修记录表】
                                // 维修记录表信息
                                RepairApplyRecord repairApplyRecord = new RepairApplyRecord();
                                repairApplyRecord.setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId())
                                        .setRepairType(RepairTypeEnum.TO_SCRAP.getTypeId()).setStatus(0L).setIsSlt(0L).setPartNum(0)
                                        .setFileIds(null == fileInfo.getId() ? "" : String.valueOf(fileInfo.getId()))
                                        .setRepairNum(BigDecimal.valueOf(0)).setScrapNum(bean.getNumberScrapRepairPartList().get(0).getScrapNum())
                                        .setScrapId(bean.getNumberScrapRepairPartList().get(0).getScrapId())
                                        .setScrapReason(bean.getNumberScrapRepairPartList().get(0).getScrapReason())
                                        .setScrapType(bean.getNumberScrapRepairPartList().get(0).getScrapType())
                                        .setRepairer(loginUser.getUsername()).setCreateBy(loginUser.getUsername());
                                // 因报废操作无需配件, 只添加【维修记录表】
                                repairMapper.addRecord(repairApplyRecord);
                            }
                        } else {
                            // 报废类型无需配件，所以配件为空，添加【维修记录表】
                            // 维修记录表信息
                            RepairApplyRecord repairApplyRecord = new RepairApplyRecord();
                            repairApplyRecord.setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId())
                                    .setRepairType(RepairTypeEnum.TO_SCRAP.getTypeId()).setStatus(0L).setIsSlt(0L).setPartNum(0)
                                    .setRepairNum(BigDecimal.valueOf(0)).setScrapNum(bean.getNumberScrapRepairPartList().get(0).getScrapNum())
                                    .setScrapReason(bean.getNumberScrapRepairPartList().get(0).getScrapReason())
                                    .setScrapType(bean.getNumberScrapRepairPartList().get(0).getScrapType())
                                    .setRepairer(loginUser.getUsername()).setCreateBy(loginUser.getUsername());
                            // 因报废操作无需配件, 只添加【维修记录表】
                            repairMapper.addRecord(repairApplyRecord);
                        }

                    }
                }
                // 拆分维修单
                splitRepairDetailsToMultiple(bean, innerRepairNum, outerRepairNum, scrapNum, loginUser);

            } else {
                throw new ServiceException("请选择正确的维修类型");
            }
        }

        return AjaxResult.success("维修完成");
    }

    /**
     * 拆分维修单,生成任务协议表
     *
     * @param newTaskId
     * @param agreementId
     * @return
     */
    private int insertTta(Long newTaskId, Long agreementId) {
        int res;
        TmTaskAgreement tmTaskAgreement = new TmTaskAgreement(newTaskId, agreementId);
        tmTaskAgreement.setCreateTime(DateUtils.getNowDate());
        tmTaskAgreement.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        res = taskAgreementMapper.insertTmTaskAgreement(tmTaskAgreement);
        return res;
    }

    /**
     * 生成任务表
     *
     * @param createBy
     * @return
     */
    private Long insertTt(String createBy) {
        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(), RepairTaskStatusEnum.TASK_LOSS_ASSESSMENT_COMPLETE.getStatus(),
                null, thisMonthMaxOrder + 1, code);
        tmTask.setCreateTime(DateUtils.getNowDate());
        tmTask.setCreateBy(createBy);
        // 插入任务
        int taskId = taskMapper.insertTmTask(tmTask);
        // 如果插入成功且返回的 taskId 大于 0
        if (taskId > 0 && tmTask.getTaskId() > 0) {
            newTask = tmTask.getTaskId();
        }
        return newTask;
    }

    /**
     * 将维修详情拆分到多个类别
     * 此方法用于根据内修、外修和报废数量更新维修记录，
     * 它首先检查提交的总维修数量是否超过实际维修数量，如果超过，则抛出异常
     * 如果本次维修完成了全部维修任务，则直接更新实际维修数量和报废数量，否则，更新本次维修和报废的数量
     *
     * @param bean           维修设备的视图对象，包含维修相关信息
     * @param innerRepairNum 内部维修数量
     * @param outerRepairNum 外部维修数量
     * @param scrapNum       报废数量
     * @param loginUser      当前登录用户信息，用于记录操作者
     * @throws ServiceException 如果本次维修提交总数过大，则抛出此异常
     */
    private void splitRepairDetailsToMultiple(RepairDeviceVO bean, BigDecimal innerRepairNum, BigDecimal outerRepairNum, BigDecimal scrapNum, LoginUser loginUser) {
        if (bean.getRepairNum().compareTo(innerRepairNum.add(outerRepairNum).add(scrapNum)) < 0) {
            throw new ServiceException("本次维修提交总数过大");
        }
        //本次修完了
        // TODO 2024-12-11 阮世耀：经过讨论 这里不管一次是否全部修完 都要先修复this 那么此判断是无意义的
        if ((bean.getRepairNum().subtract(innerRepairNum).subtract(outerRepairNum).subtract(scrapNum).compareTo(BigDecimal.valueOf(0))) == 0) {
            // TODO 2024-12-12 阮世耀：按逻辑来说 在审核之后才会PUT到真实的维修or报废数量，那么这里统一只修改this值
//            repairMapper.updateRepairedNum(bean.getId(), innerRepairNum.add(outerRepairNum) , loginUser.getUserid(), loginUser.getUserid());
//            repairMapper.updateScrapNum(bean.getId(), scrapNum, loginUser.getUserid());
            repairMapper.updateRepairedAndScrapNum(bean.getId(), innerRepairNum.add(outerRepairNum), scrapNum, loginUser.getUserid(), loginUser.getUserid());
        } else {
            // TODO 2024-12-12 阮世耀：按逻辑来说 在审核之后才会PUT到真实的维修or报废数量，那么这里统一只修改this值
//            repairMapper.updateRepairedNum(bean.getId(), innerRepairNum.add(outerRepairNum) , loginUser.getUserid(), loginUser.getUserid());
//            repairMapper.updateScrapNum(bean.getId(), scrapNum, loginUser.getUserid());
            repairMapper.updateRepairedAndScrapNum(bean.getId(), innerRepairNum.add(outerRepairNum), scrapNum, loginUser.getUserid(), loginUser.getUserid());
        }
        repairMapper.updateStatusByRepairScrapNum(bean.getId());
    }


    /**
     * 配件列表价格合计
     *
     * @param partList 配件列表
     * @param sfCosts  配件价格合计
     * @return 配件合计后的价格
     */
    private static BigDecimal countPartCosts(List<RepairPartDetails> partList, BigDecimal sfCosts) {
        for (RepairPartDetails partDetails : partList) {
            if (null != partDetails.getPartPrice() && null != partDetails.getPartNum()) {
                BigDecimal partPrice = partDetails.getPartPrice();
                BigDecimal partNumber = new BigDecimal(partDetails.getPartNum());
                sfCosts = sfCosts.add(partPrice.multiply(partNumber));
            }
        }
        return sfCosts;
    }

    /**
     * 处理配件集合数据
     *
     * @param bean       维修申请单
     * @param partList   配件列表
     * @param loginUser  当前登录用户
     * @param manageType 管理方式：0编码管理  1数量管理
     */
    private void copeNumberManageInList(RepairDeviceVO bean, List<RepairPartDetails> partList, LoginUser loginUser, Integer manageType) {
        if (CollectionUtil.isNotEmpty(partList)) {
            if (null == bean.getManageType()) {
                throw new ServiceException("请选择物资管理方式");
            }
            // 如果是数量管理，那么默认为内部维修
            if (null == bean.getRepairType() && MaTypeManageTypeEnum.NUMBER_DEVICE.getTypeId().equals(manageType)) {
                bean.setRepairType(RepairTypeEnum.INNER_REPAIR.getTypeId());
            }
            // 再检查还是null的话直接结束任务
            if (null == bean.getRepairType()) {
                return;
            }

            // 内部维修
            if (RepairTypeEnum.INNER_REPAIR.getTypeId().equals(bean.getRepairType())) {
                RepairApplyRecord repairApplyRecord = new RepairApplyRecord();
                // 遍历配件列表，判断配件类型，收费还是不收费
                for (RepairPartDetails partDetails : partList) {
                    // 维修记录表信息
                    repairApplyRecord.setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId()).setRepairType(RepairTypeEnum.INNER_REPAIR.getTypeId());
                    if (MaTypeManageTypeEnum.CODE_DEVICE.getTypeId().equals(manageType)) {
                        repairApplyRecord.setRepairNum(BigDecimal.valueOf(!RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0));
                        repairApplyRecord.setScrapNum(BigDecimal.valueOf(RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0));
                    }
                    if (MaTypeManageTypeEnum.NUMBER_DEVICE.getTypeId().equals(manageType)) {
                        repairApplyRecord.setRepairNum(partDetails.getRepairNum());
                    }
                    repairApplyRecord.setCreateBy(loginUser.getSysUser().getNickName());
                    repairApplyRecord.setStatus(0L);
                    if (bean.getInRepairList() != null) {
                        repairApplyRecord.setRemark(StringUtils.isNotBlank(bean.getInRepairList().get(0).getRemark()) ? bean.getInRepairList().get(0).getRemark() : "");
                    }

                    if ((null != partDetails.getId() || null != partDetails.getPartId()) && null != partDetails.getPartNum()) {
                        partDetails.setPartId(null != partDetails.getPartId() ? partDetails.getPartId() : partDetails.getId());
                        // 有维修配件时,如果价格为空，设置为0
                        if (null == partDetails.getPartCost()) {
                            partDetails.setPartCost(BigDecimal.ZERO);
                        }

                        partDetails.setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId()).setCompanyId(null);
                        partDetails.setCreateBy(String.valueOf(loginUser.getUserid()));

                        // 根据 partId  找配件单价
                        BigDecimal partPrice = repairMapper.selectPartPrice(partDetails.getPartId());
                        // 设置配件单价费用
                        partDetails.setPartPrice(partPrice);
                        // 添加【维修配件明细表】
                        repairMapper.addPart(partDetails);

                        // 设置维修记录的配件费用
                        repairApplyRecord.setId(bean.getId())
                                .setPartPrice(partPrice)
                                .setPartNum(partDetails.getPartNum())
                                .setRepairContent(partDetails.getRepairContent())
                                .setPartType(partDetails.getPartType())
                                .setPartId(Optional.ofNullable(partDetails.getPartId()).orElse(0L));
                        // 添加【维修记录表】
                        repairMapper.addRecord(repairApplyRecord);

                        //1、查询该附件的库存数量
                        int partNum = repairMapper.getPartNum(partDetails.getPartId());
                        if (partNum >= partDetails.getPartNum()) {
                            //2、查询所有该配件数据，数据根据数量递减，扣除数量
                            List<RepairPart> list = repairMapper.getPartList(partDetails.getPartId());
                            Integer partNums = partDetails.getPartNum();
                            for (int i = 0; i < list.size() && partNums > 0; i++) {
                                RepairPart currentPart = list.get(i);
                                if (currentPart.getPartNum() >= partNums) {
                                    // 当前记录数量足够，直接减去全部需要的数量
                                    currentPart.setPartNum(currentPart.getPartNum() - partNums);
                                    partNums = 0;
                                } else {
                                    // 当前记录数量不足，全部减去，并继续下一条记录
                                    partNums -= currentPart.getPartNum();
                                }
                                // 更新数据库中的配件数量
                                repairMapper.updatePartNum(currentPart);
                            }
                        } else {
                            throw new ServiceException("配件库存不足");
                        }

                    } else {
                        // 不选维修配件时, 只添加【维修记录表】
                        repairMapper.addRecord(repairApplyRecord);
                    }
                }
                // 根据配件id 统计配件费用
                PartType type = partTypeMapper.selectPartTypeByPaId(partList.get(0).getPartId());
                if (type != null) {
                    partList.get(0).setPartPrice(type.getBuyPrice());
                }
                BigDecimal sfCosts = countPartCosts(partList, BigDecimal.ZERO);
                // TODO: 判断是否是收费配件，因数据存在多条，可能有些是免费配件 有些收费，所以这里用价格统一做处理，后续讨论
                // SQL: 新增【维修费用记录表】
                repairApplyRecord.setRepairNum(partList.get(0).getPartNum() != null ? BigDecimal.valueOf(partList.get(0).getPartNum()) : BigDecimal.ZERO);
                //查询定损是否把价格已经添加
                int count = repairMapper.getCostCount(repairApplyRecord);
                if (count <= 0) {
                    repairMapper.addRepairCost(repairApplyRecord, sfCosts, partList.get(0).getPartType().toString());
                }
            }

            // 外部维修
            if (RepairTypeEnum.RETURN_FACTORY.getTypeId().equals(bean.getRepairType())) {
                // ---------------校验维修数量-----------------
                // 统计已维修数量 + 本次维修数量
                BigDecimal repairNum = bean.getRepairedNum().add(bean.getRepairNum());
                // 统计报废数量 + 维修合计数量  不能 大与> 总的待维修量
                if (repairNum.add(bean.getScrapNum()).compareTo(bean.getRepairNum()) > 0) {
                    throw new ServiceException("维修数量大于维修总量");
                }

                // 更新维修数量、维修人员不变
                repairMapper.updateRepairedNumTwo(bean.getId(), repairNum, loginUser.getUserid());

                // 编码管理--外部返厂维修
                if (partList != null && partList.size() > 0) {
                    for (int i = 0; i < partList.size(); i++) {
                        RepairApplyRecord repairApplyRecord = new RepairApplyRecord().setId(bean.getId()).setTaskId(bean.getTaskId()).setMaId(bean.getMaId())
                                .setTypeId(bean.getTypeId()).setRepairType(RepairTypeEnum.RETURN_FACTORY.getTypeId())
                                .setPartName(partList.get(i).getPartName())
                                .setPartType(partList.get(i).getPartType())
                                .setRepairContent(partList.get(i).getRepairContent()).setPartNum(partList.get(i).getPartNum());

                        if (null == partList.get(i).getSupplierId()) {
                            throw new ServiceException("请选择返厂厂家");
                        }
                        repairApplyRecord.setCreateBy(loginUser.getSysUser().getNickName());
                        repairApplyRecord.setSupplierId(partList.get(i).getSupplierId());
                        repairApplyRecord.setPartPrice(Optional.ofNullable(partList.get(i).getBackCost()).orElse(BigDecimal.ZERO));
                        if (!CollectionUtils.isEmpty(bean.getOutRepairList())) {
                            repairApplyRecord.setRemark(StringUtils.isNotBlank(bean.getOutRepairList().get(0).getRemark()) ? bean.getOutRepairList().get(0).getRemark() : "");
                        }
                        if (MaTypeManageTypeEnum.CODE_DEVICE.getTypeId().equals(manageType)) {
                            repairApplyRecord.setRepairNum(BigDecimal.valueOf(!RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0));
                            repairApplyRecord.setScrapNum(BigDecimal.valueOf(RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0));
                        }
                        if (MaTypeManageTypeEnum.NUMBER_DEVICE.getTypeId().equals(manageType)) {
                            repairApplyRecord.setRepairNum(partList.get(i).getRepairNum());
                        }

                        // 新增【维修记录表】
                        repairMapper.addRecord(repairApplyRecord);

                        // 配件费用计算
                        BigDecimal sfCosts = partList.get(i).getBackCost() != null ? partList.get(i).getBackCost() : BigDecimal.ZERO;

                        // TODO: 判断是否是收费配件，因数据存在多条，可能有些是免费配件 有些收费，所以这里用价格统一做处理，后续讨论
                        // SQL: 新增【维修费用记录表】
                        repairApplyRecord.setRepairNum(partList.get(i).getPartNum() != null ? BigDecimal.valueOf(partList.get(i).getPartNum()) : BigDecimal.ZERO);
                        //查询定损是否把价格已经添加
                        int count = repairMapper.getCostCount(repairApplyRecord);
                        if (count <= 0) {
                            repairMapper.addRepairCost(repairApplyRecord, sfCosts, partList.get(i).getPartType().toString());
                        }
                    }
                }

            }

            // 如果是报废类型，进行上传附件相关处理
            if (RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType())) {
                if (CollectionUtil.isNotEmpty(partList.get(0).getFileList())) {
                    for (BmFileInfo fileInfo : partList.get(0).getFileList()) {
                        fileInfo.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR.getTaskTypeId())
                                .setFileType(Long.valueOf(RepairTypeEnum.TO_SCRAP.getTypeId()))
                                .setTaskId(bean.getTaskId()).setModelId(bean.getId())
                                .setCreateBy(loginUser.getUsername());
                        bmFileInfoMapper.insertBmFileInfo(fileInfo);

                        // 配件为空，添加【维修记录表】
                        RepairApplyRecord repairApplyRecord = new RepairApplyRecord();
                        repairApplyRecord.setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId())
                                .setRepairType(bean.getRepairType()).setStatus(0L).setFileIds(String.valueOf(fileInfo.getId()))
                                .setRepairNum(BigDecimal.valueOf(!RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0))
                                .setScrapNum(BigDecimal.valueOf(RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0))
                                .setCreateBy(loginUser.getUsername());
                        repairApplyRecord.setScrapType(partList.get(0).getScrapType());
                        repairApplyRecord.setScrapReason(partList.get(0).getScrapReason());
                        repairApplyRecord.setScrapId(partList.get(0).getScrapId());
                        // 不选维修配件时, 只添加【维修记录表】
                        repairMapper.addRecord(repairApplyRecord);
                    }
                } else {
                    // 配件为空，添加【维修记录表】
                    RepairApplyRecord repairApplyRecord = new RepairApplyRecord();
                    repairApplyRecord.setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId())
                            .setRepairType(bean.getRepairType()).setStatus(0L)
                            .setRepairNum(BigDecimal.valueOf(!RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0))
                            .setScrapNum(BigDecimal.valueOf(RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0))
                            .setCreateBy(loginUser.getUsername());
                    repairApplyRecord.setScrapType(partList.get(0).getScrapType());
                    repairApplyRecord.setScrapReason(partList.get(0).getScrapReason());
                    repairApplyRecord.setScrapId(partList.get(0).getScrapId());
                    // 不选维修配件时, 只添加【维修记录表】
                    repairMapper.addRecord(repairApplyRecord);
                }
            }

        } else {
            // 配件为空，添加【维修记录表】
            RepairApplyRecord repairApplyRecord = new RepairApplyRecord();
            repairApplyRecord.setTaskId(bean.getTaskId()).setMaId(bean.getMaId()).setTypeId(bean.getTypeId())
                    .setRepairType(bean.getRepairType()).setStatus(0L)
                    .setRepairNum(BigDecimal.valueOf(!RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0))
                    .setScrapNum(BigDecimal.valueOf(RepairTypeEnum.TO_SCRAP.getTypeId().equals(bean.getRepairType()) ? 1 : 0))
                    .setCreateBy(loginUser.getUsername());
            repairApplyRecord.setRemark(StringUtils.isNotBlank(bean.getRemark()) ? bean.getRemark() : "");
            // 不选维修配件时, 只添加【维修记录表】
            repairMapper.addRecord(repairApplyRecord);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult endRepairTask(@NotNull List<RepairTask> taskList) {
        LoginUser loginUser = SecurityUtils.getLoginUser();

        try {
            // 1.查询选择任务是否还有未完成维修的数据
            for (RepairTask task : taskList) {
                // 查询选择的任务中是否存在未维修的单子，进行不能提交审核提醒
                List<RepairTaskDetails> detailsList = repairApplyDetailsMapper.getRepairDetailsWhichNotSent(task.getTaskId());
                if (!CollectionUtils.isEmpty(detailsList)) {
                    BigDecimal repairedNum = BigDecimal.ZERO;
                    BigDecimal scrapNum = BigDecimal.ZERO;
                    String taskCode = "";
                    for (RepairTaskDetails repairTaskDetails : detailsList) {
                        repairedNum = repairedNum.add(repairTaskDetails.getRepairedNum());
                        scrapNum = scrapNum.add(repairTaskDetails.getScrapNum());
                        taskCode = repairTaskDetails.getTaskCode();
                    }
                    if (repairedNum.add(scrapNum).compareTo(BigDecimal.ZERO) == 0) {
                        return AjaxResult.error("维修单号" + taskCode + "还未进行维修，请先维修后再提交审核！");
                    }
                }
            }

            // 3.业务逻辑处理
            for (RepairTask task : taskList) {
                Long agreementId = null;
                // 查询维修任务的详情表
                Long oldWxTaskId = task.getTaskId();
                List<RepairTaskDetails> detailsList = repairApplyDetailsMapper.getRepairDetailsWhichNotSent(oldWxTaskId);
                repairMapper.updateSingleTaskStatus(task, loginUser.getUserid(), RepairTaskStatusEnum.TASK_STATUS_COMPLETE.getStatus());
                // 维修拆分标志
                boolean isWxFlag = false;
                // 维修拆分数据集合
                List<RepairTaskDetails> repairTaskDetails = new ArrayList<>();
                if (!CollectionUtils.isEmpty(detailsList)) {
                    task.setCreateBy(loginUser.getUserid());
                    agreementId = repairMapper.getAgreementId(task);
                    // 新增tm_task表数据、修饰审核任务、状态是待审核
                    task.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR_AUDIT.getTaskTypeId());
                    task.setTaskStatus(RepairTaskStatusEnum.TASK_STATUS_TO_EXAM.getStatus());
                    int thisMonthMaxOrder = taskMapper.getMonthMaxOrderByDate(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth(), TmTaskTypeEnum.TM_TASK_REPAIR_AUDIT.getTaskTypeId());
                    // 生成维修单号
                    String code = genderWsTaskCode(thisMonthMaxOrder);
                    task.setRepairCode(code);
                    task.setMonthOrder(thisMonthMaxOrder + 1);
                    // 插入之前的维修任务id标记前置任务
                    task.setPreTaskId(task.getTaskId());
                    // 注意：此处将会生成新的 taskId （审核入库用的）
                    repairMapper.addTask(task);
                    // 新增协议任务表tm_task_agreement--关联修饰任务与协议
                    task.setAgreementId(agreementId);
                    repairMapper.createAgreementTask(task);
                    // 新增审计记录
                    for (RepairTaskDetails details : detailsList) {
                        if (StringUtils.isNotBlank(details.getMaId())) {
                            if ("0".equals(details.getStatus())) {
                                isWxFlag = true;
                                details.setLevel((StringUtils.isNotBlank(details.getLevel())) ? String.valueOf(Integer.parseInt(details.getLevel()) + 1) : "1");
                                details.setParentId(details.getId());
                                repairTaskDetails.add(details);
                                continue;
                            }
                        } else {
                            BigDecimal repairNum = details.getRepairNum();
                            BigDecimal repairedNum = details.getRepairedNum();
                            BigDecimal scrapNum = details.getScrapNum();
                            if (repairedNum.add(scrapNum).compareTo(repairNum) < 0) {
                                isWxFlag = true;
                                RepairTaskDetails taskDetails = new RepairTaskDetails();
                                taskDetails.setRepairNum(repairNum.subtract(repairedNum).subtract(scrapNum));
                                taskDetails.setTypeId(details.getTypeId());
                                taskDetails.setLevel((StringUtils.isNotBlank(details.getLevel())) ? String.valueOf(Integer.parseInt(details.getLevel()) + 1) : "1");
                                taskDetails.setParentId(details.getId());
                                taskDetails.setBackId(details.getBackId());
                                repairTaskDetails.add(taskDetails);
                            }
                        }
                        details.setCreateBy(String.valueOf(loginUser.getUserid()));
                        details.setTaskId(task.getTaskId());
                        details.setRepairNum(details.getRepairedNum()
                                .add(details.getScrapNum()));
                        // 将待修状态改为已维修
                        int result = repairMapper.updateStatus(details);
                        if (result <= 0) {
                            throw new ServiceException("待修状态修改失败");
                        }
                        // 先根据id查询审核表中是否存在数据，存在则不用重复插入
                        if (CollectionUtils.isEmpty(repairMapper.getAuditDetailsById(details))) {
                            // 如果合格数和报废数都为0，则未进行维修，不插入审核表
                            if (details.getRepairedNum().compareTo(BigDecimal.ZERO) == 0 &&
                                    details.getScrapNum().compareTo(BigDecimal.ZERO) == 0) {
                                continue;
                            }
                            result = repairMapper.addAuditDetails(details);
                            if (result <= 0) {
                                throw new ServiceException("审核任务插入失败");
                            }
                        }
                    }
                }
                // 进行维修拆分
                if (isWxFlag) {
                    // 插入任务表
                    Long newTaskId = insertTt(SecurityUtils.getLoginUser().getSysUser().getNickName());
                    // 插入协议任务表
                    int res = insertTta(newTaskId, agreementId);
                    if (res <= 0) {
                        throw new ServiceException("协议任务表插入失败");
                    }
                    if (!CollectionUtils.isEmpty(repairTaskDetails)) {
                        for (RepairTaskDetails repairTaskDetail : repairTaskDetails) {
                            repairTaskDetail.setTaskId(newTaskId);
                            repairTaskDetail.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
                            repairTaskDetail.setStatus("0");
                            repairTaskDetail.setNewTaskId(newTaskId);
                            repairTaskDetail.setIsDs(0);
                            repairMapper.insertRepaired(repairTaskDetail);
                        }
                    } else {
                        throw new ServiceException("维修拆分数据组装错误");
                    }
                }
            }
            return AjaxResult.success("提交审核成功");
        } catch (ServiceException e) {
            log.error("执行异常", e);
            return AjaxResult.error("数据处理异常，请联系管理员");
        }
    }

    /**
     * 获取前置任务详情
     *
     * @param repairTaskDetails
     * @return
     */
    private List<RepairTaskDetails> getPreDetailsForTask(RepairTaskDetails repairTaskDetails) {
        // 如果 parentId 为 0，表示达到了根任务，返回当前任务列表
        if (repairTaskDetails.getParentId() == 0) {
            return Collections.singletonList(repairTaskDetails);
        }

        // 否则，继续递归查询上一个任务
        List<RepairTaskDetails> preDetailsList = repairApplyDetailsMapper.getRepairDetails(repairTaskDetails.getPreTaskId());
        if (!CollectionUtils.isEmpty(preDetailsList)) {
            for (RepairTaskDetails preRepairTaskDetails : preDetailsList) {
                if (preRepairTaskDetails.getParentId() != null && preRepairTaskDetails.getParentId() != 0) {
                    // 递归查询父任务
                    return getPreDetailsForTask(preRepairTaskDetails);
                } else {
                    // 找到 parentId 为 0 的任务，返回该任务
                    return Collections.singletonList(preRepairTaskDetails);
                }
            }
        }
        return Collections.emptyList(); // 如果没有找到，返回空列表
    }

    private static RepairApplyDetails createRepairDetailsCope(RepairTaskDetails details) {
        RepairApplyDetails repairApplyDetails = new RepairApplyDetails();
        repairApplyDetails.setId(details.getId());
        repairApplyDetails.setRepairedNum((details.getRepairedNum().add(details.getThisRepairedNum())));
        repairApplyDetails.setThisRepairedNum(BigDecimal.valueOf(0));
        repairApplyDetails.setScrapNum((details.getScrapNum().add(details.getThisScrapNum())));
        repairApplyDetails.setThisScrapNum(BigDecimal.valueOf(0));
        return repairApplyDetails;
    }

    /**
     * 生成维修审核单号
     *
     * @param thisMonthMaxOrder 当前月最大序号
     */
    private String genderWsTaskCode(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_AUDIT_TYPE_LABEL + result + String.format("-%03d", thisMonthMaxOrder + 1);
    }

    /**
     * 生成维修单号
     *
     * @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 bean
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult rejectRepair(RepairTask bean) {
        try {
            if (!CollectionUtils.isEmpty(bean.getTaskIds())) {
                for (Long taskId : bean.getTaskIds()) {
                    // 判断维修明细是否有已经维修的数据
                    final int repairedScrapNumber = repairMapper.getRepairedScrapNumByTaskId(taskId);
                    final TmTask tmTask = taskMapper.selectTmTaskByTaskId(taskId);
                    if (0 >= repairedScrapNumber) {
                        //驳回操作不可跨月操作
                        if (!StringHelper.isNullOrEmptyString(String.valueOf(tmTask.getCreateTime()))) {
                            // 将 createTime 转换为 LocalDate
                            LocalDate taskCreationDate = tmTask.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                            // 获取当前日期
                            LocalDate today = LocalDate.now();
                            // 检查是否在同一月
                            if (taskCreationDate.getYear() != today.getYear() || taskCreationDate.getMonth() != today.getMonth()) {
                                throw new ServiceException("只可驳回本月任务");
                            }
                        }
                        // 1.驳回后直接清楚该条维修单记录
                        int result = taskMapper.deleteTmTaskByTaskId(taskId);
                        if (result < 1) {
                            throw new ServiceException("维修驳回失败，请联系管理员");
                        }
                        if (null != tmTask.getPreTaskId()) {
                            // 2. 根据任务id查询前置任务数据详情
                            BackApplyInfo info = backApplyInfoMapper.selectByTaskId(tmTask.getPreTaskId());
                            // 3. 查询back_check_details表数据
                            BackCheckDetails backCheckDetails = new BackCheckDetails();
                            backCheckDetails.setParentId(info.getId());
                            List<BackCheckDetails> checkDetails = backCheckDetailsMapper.selectBackCheckDetailsList(backCheckDetails);
                            // 4. 更新结算信息表
                            result = sltAgreementInfoMapper.backRejectSltCope(tmTask.getPreTaskId());
                            if (result < 1) {
                                throw new ServiceException("维修驳回失败，请联系管理员");
                            }
                            // 5. 对于编码设备，更改设备状态为在用
                            if (!CollectionUtils.isEmpty(checkDetails)) {
                                for (BackCheckDetails backCheckDetail : checkDetails) {
                                    if (backCheckDetail.getMaId() != null) {
                                        // 更新设备状态为在用
                                        machineMapper.updateStatus(backCheckDetail.getMaId(), MaMachineStatusEnum.IN_USE.getStatus());
                                    }
                                }
                            }
                            //修改退料任务的状态，以及退料详情里面的状态
                            int res = taskMapper.updateTaskStatus(String.valueOf(taskId), 1);
                            // 4. 删除维修明细数据
                            result = repairMapper.deleteByTaskId(taskId);
                            if (result < 1) {
                                throw new ServiceException("维修驳回失败，请联系管理员");
                            }
                            extractedTaskId(taskId);
                        } else {
                            throw new ServiceException("维修任务没有前置任务，不能驳回");
                        }
                    } else {
                        throw new ServiceException("维修任务已有维修数据，不能驳回");
                    }
                }
            } else if (!CollectionUtils.isEmpty(bean.getIds())) {
                RepairApplyDetails repairApplyDetails = null;
                for (Long id : bean.getIds()) {
                    int repairedScrapNumber = repairMapper.getRepairedScrapNumById(id);
                    if (repairedScrapNumber > 0) {
                        throw new ServiceException("维修明细已有维修数据，不能驳回");
                    }
                }
                for (Long id : bean.getIds()) {
                    // 查询明细详情
                    repairApplyDetails = repairApplyDetailsMapper.selectRepairApplyDetailsById(id);
                    if (repairApplyDetails != null) {
                        if (repairApplyDetails.getMaId() != null) {
                            machineMapper.updateStatus(repairApplyDetails.getMaId(), MaMachineStatusEnum.IN_USE.getStatus());
                        }
                    }
                    // 驳回后直接清除该条维修单记录
                    int result = repairMapper.deleteRepairById(id);
                    if (result < 1) {
                        throw new ServiceException("维修驳回失败，请联系管理员");
                    }
                    // 更新结算信息表
                    if (repairApplyDetails != null) {
                        TmTask tmTask = taskMapper.selectTmTaskByTaskId(repairApplyDetails.getTaskId());
                        repairApplyDetails.setPreTaskId(tmTask.getPreTaskId());
                        result = sltAgreementInfoMapper.backInUseNum(repairApplyDetails);
                        if (result < 1) {
                            throw new ServiceException("维修驳回失败，请联系管理员");
                        }
                        extractedByDetails(repairApplyDetails);
                    }
                }
            }
        } catch (final DataAccessException e) {
            System.err.println(e.getMessage());
            throw new ServiceException("数据库SQL修改执行失败" + e.getMessage());
        }
        return AjaxResult.success("执行完成");
    }

    /**
     * 驳回至退料详情方法抽取
     *
     * @param repairApplyDetails
     */
    private void extractedByDetails(RepairApplyDetails repairApplyDetails) {
        int result;
        // 5.先根据taskId查询repair_apply_record表是否存在数据，存在则删除
        RepairAuditDetails repairAuditDetails = new RepairAuditDetails();
        repairAuditDetails.setTaskId(repairApplyDetails.getTaskId());
        repairAuditDetails.setTypeId(repairApplyDetails.getTypeId());
        repairAuditDetails.setMaId(repairApplyDetails.getMaId() == null ? null : repairApplyDetails.getMaId());
        List<RepairRecord> repairRecord = repairAuditDetailsMapper.getRepairRecord(repairAuditDetails);
        if (!CollectionUtils.isEmpty(repairRecord)) {
            result = repairAuditDetailsMapper.deleteRepairRecordByTaskId(repairAuditDetails);
            if (result < 1) {
                throw new ServiceException("维修驳回失败，请联系管理员");
            }
        }
        // 6. 先根据taskId查询repair_cost表是否存在数据，存在则删除
        RepairCost repairCost = new RepairCost();
        repairCost.setTaskId(repairApplyDetails.getTaskId());
        repairCost.setTypeId(repairApplyDetails.getTypeId());
        repairCost.setMaId(repairApplyDetails.getMaId() == null ? null : repairApplyDetails.getMaId());
        List<RepairCost> repairCosts = repairCostMapper.selectRepairCostList(repairCost);
        if (!CollectionUtils.isEmpty(repairCosts)) {
            result = repairCostMapper.deleteRepairCostByTaskId(repairCost);
            if (result < 1) {
                throw new ServiceException("维修驳回失败，请联系管理员");
            }
        }
        // 7. 先根据taskId查询repair_part_details表是否存在数据，存在则删除
        RepairPartDetails repairPartDetails = new RepairPartDetails();
        repairPartDetails.setTaskId(repairApplyDetails.getTaskId());
        repairPartDetails.setTypeId(repairApplyDetails.getTypeId());
        repairPartDetails.setMaId(repairApplyDetails.getMaId() == null ? null : repairApplyDetails.getMaId());
        List<RepairPartDetails> repairPartDetailList = repairPartDetailsMapper.selectRepairPartDetailsList(repairPartDetails);
        if (!CollectionUtils.isEmpty(repairPartDetailList)) {
            result = repairPartDetailsMapper.deleteRepairCostByTaskId(repairPartDetails);
            if (result < 1) {
                throw new ServiceException("维修驳回失败，请联系管理员");
            }
        }
    }

    /**
     * 驳回至退料任务单抽取
     *
     * @param taskId
     */
    private void extractedTaskId(Long taskId) {
        int result;
        // 5.先根据taskId查询repair_apply_record表是否存在数据，存在则删除
        RepairAuditDetails repairAuditDetails = new RepairAuditDetails();
        repairAuditDetails.setTaskId(taskId);
        List<RepairRecord> repairRecord = repairAuditDetailsMapper.getRepairRecord(repairAuditDetails);
        if (!CollectionUtils.isEmpty(repairRecord)) {
            result = repairAuditDetailsMapper.deleteRepairRecordByTaskId(repairAuditDetails);
            if (result < 1) {
                throw new ServiceException("维修驳回失败，请联系管理员");
            }
        }
        // 6. 先根据taskId查询repair_cost表是否存在数据，存在则删除
        RepairCost repairCost = new RepairCost();
        repairCost.setTaskId(taskId);
        List<RepairCost> repairCosts = repairCostMapper.selectRepairCostList(repairCost);
        if (!CollectionUtils.isEmpty(repairCosts)) {
            result = repairCostMapper.deleteRepairCostByTaskId(repairCost);
            if (result < 1) {
                throw new ServiceException("维修驳回失败，请联系管理员");
            }
        }
        // 7. 先根据taskId查询repair_part_details表是否存在数据，存在则删除
        RepairPartDetails repairPartDetails = new RepairPartDetails();
        repairPartDetails.setTaskId(taskId);
        List<RepairPartDetails> repairPartDetailList = repairPartDetailsMapper.selectRepairPartDetailsList(repairPartDetails);
        if (!CollectionUtils.isEmpty(repairPartDetailList)) {
            result = repairPartDetailsMapper.deleteRepairCostByTaskId(repairPartDetails);
            if (result < 1) {
                throw new ServiceException("维修驳回失败，请联系管理员");
            }
        }
    }

    /**
     * 维修明细--批量合格--更新明细status，以及repairedNum
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchQualified(ArrayList<Long> ids) {
        repairMapper.updateMaMachine(ids, SecurityUtils.getLoginUser().getSysUser().getNickName());
        return repairMapper.batchQualified(ids, SecurityUtils.getLoginUser().getSysUser().getNickName());
    }

    @Override
    public List<SysUser> selectUserList() {
        return repairMapper.selectUserList();
    }

    @Override
    public List<RepairInputDetailsVo> getRepairedList(RepairInputDetailsVo dto) {
        return repairMapper.getRepairedList(dto);
    }

    @Override
    public List<RepairInputDetailsVo> getRepairedDetailList(RepairInputDetailsVo dto) {
        List<RepairInputDetailsVo> repairedDetailList = repairMapper.getRepairedDetailList(dto);
//        for (RepairInputDetailsVo repairTestInputDetailVo : repairedDetailList) {
//            List<String> userIds = repairMapper.selectKeepUser(repairTestInputDetailVo.getTypeId());
//            userIds.add("1");
//            repairTestInputDetailVo.setUserIds(userIds);
//        }
        return repairedDetailList;
    }

    /**
     * 获取维修明细列表
     *
     * @param bean
     * @return
     */
    @Override
    public List<RepairPartDetails> getDetailsList(RepairPartDetails bean) {
        return repairMapper.getDetailsList(bean);
    }

    @Override
    public List<RepairPartDetails> getDetailsListApp(RepairPartDetails bean) {
        try {
//            List<RepairPartDetails> list = repairMapper.getDetailsListApp(bean);
//            if (list.size()<=0){
                List<RepairPartDetails> list=repairMapper.getDetailsListAppTwo(bean);
//            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    @Override
    public List<RepairPartInfo> getLossPart(RepairPartInfo bean) {
        try {
            // 使用 Map 来临时存储 partId -> RepairPartInfo 映射
            Map<String, RepairPartInfo> partInfoMap = new HashMap<>();
            if (bean.getIds() != null && bean.getIds().length > 0) {
                for (int id : bean.getIds()) {
                    //如果是数量的设备，已经提交过一次，则第二次不查询配件了
                    RepairPartInfo bean1 = repairMapper.getPartCount(id);
                    if (bean1.getPartNum() != null && bean1.getPartNum().compareTo(BigDecimal.ZERO) > 0) {
                        continue;
                    }
                    // 查询配件
                    List<RepairPartInfo> tempList = repairMapper.getLossPart(id);
                    for (RepairPartInfo partInfo : tempList) {
                        String partId = String.valueOf(partInfo.getPartId());
                        BigDecimal currentPartNum = partInfo.getPartNum() == null ? BigDecimal.ZERO : partInfo.getPartNum();
                        if (partInfoMap.containsKey(partId)) {
                            // 已存在，累加 partNum
                            RepairPartInfo existingPart = partInfoMap.get(partId);
                            BigDecimal existingNum = existingPart.getPartNum() == null ? BigDecimal.ZERO : existingPart.getPartNum();
                            existingPart.setPartNum(existingNum.add(currentPartNum));
                        } else {
                            // 第一次放入，避免原对象被修改，可选是否深拷贝
                            partInfo.setPartNum(currentPartNum);
                            partInfoMap.put(partId, partInfo);
                        }
                    }
                }
            }
            // 返回合并后的结果
            return new ArrayList<>(partInfoMap.values());
        } catch (Exception e) {
            log.error(e.getMessage());
            return Collections.emptyList();
        }
    }

    @Override
    public List<RepairTaskDetails> getRepairCodeList(RepairTaskDetails bean) {
        try {
            return repairMapper.getRepairCodeList(bean);
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    @Override
    public List<RepairTaskDetails> getTestRecordData(RepairTaskDetails bean) {
        try {
            //查询
            List<RepairTaskDetails> list = repairMapper.getTestRecordData(bean);
            if (list.size() > 0) {
                for (RepairTaskDetails bean1 : list) {
                    bean1.setUserName(SecurityUtils.getLoginUser().getSysUser().getNickName());
                    //查询配件列表
                    List<PartType> partList = repairMapper.getPartData(bean1);
                    if (partList.size() > 0) {
                        bean1.setPartTypeList(partList);
                    }
                }
            }
            return list;
        } catch (Exception e) {
            log.error("查询试验记录表", e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public List<RepairDeviceVO> getAppRepairMaTypeListByTaskIdAndTypeId(RepairTaskDetails bean) {
        try {
            return repairMapper.getAppRepairMaTypeListByTaskIdAndTypeId(bean);
        } catch (Exception e) {
            log.error("查询修试查询-维修配件查询列表", e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * @param dto
     * @return
     */
    @Override
    public List<RepairInspection> getRepairInspection(RepairInspection dto) {
        return repairMapper.getRepairInspection(dto);
    }

    /**
     * @param dto
     * @return
     */
    @Override
    public List<TestRecord> getTestRecord(TestRecord dto) {
        return repairMapper.getTestRecord(dto);
    }

    /**
     * @param bean
     * @return
     */
    @Override
    public List<RepairTaskDetails> getTestRecordDetails(TestRecord bean) {
        try {
            //查询
            List<RepairTaskDetails> list = repairMapper.getTestRecordDetails(bean);
            if (list.size() > 0) {
                for (RepairTaskDetails bean1 : list) {
                    bean1.setUserName(SecurityUtils.getLoginUser().getSysUser().getNickName());
                    //查询配件列表
                    List<PartType> partList = repairMapper.getPartDetails(bean1);
                    if (partList.size() > 0) {
                        bean1.setPartTypeList(partList);
                    }
                }
            }
            return list;
        } catch (Exception e) {
            log.error("查询试验记录表", e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public List<RepairDeviceSummaryVo> getAppRepairMaTypeListNew(RepairTaskDetails bean) {
        try {
            Long userId = SecurityUtils.getLoginUser().getUserid();
            // 首先根据用户名去ma_type_manage表查询是否存在绑定物资信息
            /*List<Long> typeIdList = backApplyInfoMapper.selectTypeIdList(userId);
            if (CollectionUtils.isEmpty(typeIdList)) {
                bean.setUserId(userId == 0 ? null : userId);
            }*/
            Set<String> userRoles = SecurityUtils.getLoginUser().getRoles();
            // 检查用户是否具有特殊角色
            boolean hasSpecialRole = hasSpecialRole(userRoles);
            if (!hasSpecialRole) {
                bean.setUserId(userId == 0 ? null : userId);
            }
            List<RepairDeviceSummaryVo> repairDeviceSummaryVoList = new ArrayList<>();
            List<RepairDeviceVO> repairDeviceList = repairMapper.getAppRepairMaTypeListNew(bean);
            Map<Long, List<RepairDeviceVO>> map = repairDeviceList.stream().collect(Collectors.groupingBy(RepairDeviceVO::getTypeId));
            for (Long key : map.keySet()) {
                List<RepairDeviceVO> tempList = map.get(key);
                if (CollectionUtil.isNotEmpty(tempList)) {
                    RepairDeviceSummaryVo vo = new RepairDeviceSummaryVo();
                    Long[] ids = tempList.stream().map(RepairDeviceVO::getId).toArray(Long[]::new);
                    BigDecimal repairNumSum = tempList.stream()
                            .map(RepairDeviceVO::getRepairNum)
                            .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal repairedNumSum = tempList.stream()
                            .map(RepairDeviceVO::getRepairedNum)
                            .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal scrapNumSum = tempList.stream()
                            .map(RepairDeviceVO::getScrapNum)
                            .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal completeNum = tempList.stream()
                            .map(RepairDeviceVO::getCompleteNum)
                            .map(num -> Optional.ofNullable(num).orElse(BigDecimal.ZERO))
                            .reduce(BigDecimal.ZERO, BigDecimal::add);

                    Integer dataStatusSum = tempList.stream()
                            .map(RepairDeviceVO::getDataStatus)
                            .filter(Objects::nonNull)
                            .map(status -> "1".equals(status) ? 1 : 0) // 安全转换
                            .reduce(0, Integer::sum);
                    BigDecimal waitRepairNum = repairNumSum.subtract(repairedNumSum).subtract(scrapNumSum);
                    BigDecimal typeCostSum = tempList.stream().map(RepairDeviceVO::getTotalCost).reduce(BigDecimal.ZERO, BigDecimal::add);
                    vo.setRepairDeviceList(tempList)
                            .setIds(ids).setTypeRepairNum(repairNumSum).setTypeRepairedNum(repairedNumSum)
                            .setTypeScrapNum(scrapNumSum).setTaskId(tempList.get(0).getTaskId())
                            .setCode(tempList.get(0).getCode()).setTypeName(tempList.get(0).getTypeName())
                            .setTypeId(tempList.get(0).getTypeId()).setType(tempList.get(0).getType())
                            .setUnitName(tempList.get(0).getUnitName()).setManageType(tempList.get(0).getManageType())
                            .setDataStatusNum(dataStatusSum)
                            .setUnitValue(tempList.get(0).getUnitValue())
                            .setWaitRepairNum(waitRepairNum)
                            .setCompleteNum(completeNum)
                            .setTypeCost(typeCostSum);
                    repairDeviceSummaryVoList.add(vo);
                }
            }
            return repairDeviceSummaryVoList;
        } catch (Exception e) {
            log.error("查询修试查询-维修配件查询列表", e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * 查询在修工程维修列表
     * @param bean
     * @return
     */
    @Override
    public List<RepairProjectInfo> getRepairProjectList(RepairProjectInfo bean) {
        try {
            return repairMapper.getRepairProjectList(bean);
        } catch (Exception e) {
            log.error("查询在修工程维修列表", e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * 查询修试查询-维修配件查询列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<RepairPartVo> selectRepairPartList(RepairPartVo dto) {
        // 查询维修配件列表
        List<RepairPartVo> list = repairMapper.selectRepairPartList(dto);
        if (!CollectionUtils.isEmpty(list)) {
            for (RepairPartVo repairPartVo : list) {
                // 查询配件相关信息
                RepairPartVo info = repairMapper.selectRepairPartInfo(repairPartVo);
                if (info != null) {
                    repairPartVo.setPartName(StringUtils.isNotBlank(info.getPartName()) ? info.getPartName() : null);
                    repairPartVo.setPartModelName(StringUtils.isNotBlank(info.getPartModelName()) ? info.getPartModelName() : null);
                    repairPartVo.setPartNum(info.getPartNum());
                    repairPartVo.setRepairPerson(StringUtils.isNotBlank(info.getRepairPerson()) ? info.getRepairPerson() : null);
                }
            }
            // 如果关键字不为空，根据关键字查询
            if (!StringUtils.isBlank(dto.getKeyWord())) {
                list = list.stream()
                        .filter(item -> containsBackKeyword(item, dto.getKeyWord()))
                        .collect(Collectors.toList());
            }
        }
        return list;
    }

    /**
     * 查询修试查询-维修配件查询二级列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<RepairPartInfo> selectSecondRepairPartList(RepairPartInfo dto) {
        List<RepairPartInfo> list = repairMapper.selectSecondRepairPartList(dto);
        if (!CollectionUtils.isEmpty(list)) {
            // 如果关键字不为空，根据关键字查询
            if (!StringUtils.isBlank(dto.getKeyWord())) {
                list = list.stream()
                        .filter(item -> containsRepairKeyword(item, dto.getKeyWord()))
                        .collect(Collectors.toList());
            }
        }
        return list;
    }

    /**
     * 判断维修配件查询二级列表是否包含关键字
     *
     * @param item
     * @param keyWord
     * @return
     */
    private boolean containsRepairKeyword(RepairPartInfo item, String keyWord) {
        return (item.getPartName() != null && item.getPartName().contains(keyWord)) ||
                (item.getPartModelName() != null && item.getPartModelName().contains(keyWord));
    }

    /**
     * 判断维修配件查询列表是否包含关键字
     *
     * @param item
     * @param keyWord
     * @return
     */
    private boolean containsBackKeyword(RepairPartVo item, String keyWord) {
        return (item.getTypeName() != null && item.getTypeName().contains(keyWord)) ||
                (item.getTypeModelName() != null && item.getTypeModelName().contains(keyWord)) ||
                (item.getRepairPerson() != null && item.getRepairPerson().contains(keyWord)) ||
                (item.getBackUnitName() != null && item.getBackUnitName().contains(keyWord)) ||
                (item.getBackProName() != null && item.getBackProName().contains(keyWord)) ||
                (item.getPartName() != null && item.getPartName().contains(keyWord)) ||
                (item.getPartModelName() != null && item.getPartModelName().contains(keyWord)) ||
                (item.getRepairCode() != null && item.getRepairCode().contains(keyWord)) ||
                (item.getMaCode() != null && item.getMaCode().contains(keyWord));
    }
}
