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

import cn.hutool.core.collection.CollectionUtil;
import com.bonus.common.biz.enums.MaTypeManageTypeEnum;
import com.bonus.common.biz.enums.RepairTaskStatusEnum;
import com.bonus.common.biz.enums.RepairTypeEnum;
import com.bonus.common.biz.enums.TmTaskTypeEnum;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.basic.domain.BmFileInfo;
import com.bonus.material.basic.mapper.BmFileInfoMapper;
import com.bonus.material.repair.domain.*;
import com.bonus.material.repair.domain.vo.RepairDeviceSummaryVo;
import com.bonus.material.repair.domain.vo.RepairDeviceVO;
import com.bonus.material.repair.domain.vo.RepairInputDetailsVo;
import com.bonus.material.repair.domain.vo.RepairTicketVo;
import com.bonus.material.repair.mapper.RepairApplyDetailsMapper;
import com.bonus.material.repair.mapper.RepairAuditDetailsMapper;
import com.bonus.material.repair.mapper.RepairMapper;
import com.bonus.material.repair.service.RepairService;
import com.bonus.material.task.mapper.TmTaskMapper;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
import org.springframework.beans.BeanUtils;
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.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author syruan
 */
@Service("RepairService")
@Validated
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;

    // 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();

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

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

    @Override
    public List<RepairDeviceSummaryVo> getRepairDeviceSummary(RepairTaskDetails bean) {
        List<RepairDeviceSummaryVo> repairDeviceSummaryVoList = new ArrayList<>();
        List<RepairDeviceVO> repairDeviceList = repairMapper.getRepairDeviceList(bean);
        Map<Long, List<RepairDeviceVO>> map = repairDeviceList.stream().collect(Collectors.groupingBy(RepairDeviceVO::getTypeId));
        for (Long key : map.keySet()) {
            List<RepairDeviceVO> tempList = map.get(key);
//            List<RepairDeviceVO> toRepairList = tempList.stream().filter(o -> !"1".equals(o.getStatus())).collect(Collectors.toList());
            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 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());
//                        .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);
            RepairTicketVo result = new RepairTicketVo()
                    .setRepairTaskInfo(repairTaskInfo)
                    .setRepairDeviceSummaryList(repairDeviceSummaryList)
                    .setRepairPartArray(Optional.of(repairPartList).orElse(new ArrayList<>()));

            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(new BigDecimal(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 (bean == null || bean.getRepairType() == null) {
            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());
            bean.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 num = scrapNum.add(details.getRepairedNum()) ;
                if (num.compareTo( details.getRepairNum()) >0) {
                    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 (partDetails.getPartId() != null) {
                        // 有维修配件时,如果价格为空，设置为0
                        if (partDetails.getPartCost() == null) {
                            partDetails.setPartCost(BigDecimal.ZERO);
                        }
                        partDetails.setTaskId(bean.getTaskId());
                        partDetails.setMaId(bean.getMaId());
                        partDetails.setTypeId(bean.getTypeId());
                        partDetails.setCreateBy(String.valueOf(loginUser.getUserid()));
                        partDetails.setCompanyId(bean.getCompanyId());

                        // 根据 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 (partList.get(0).getSupplierId() == null) {
                    throw new ServiceException("请选择返厂厂家");
                } else {
                    bean.setSupplierId(partList.get(0).getSupplierId());
                }
                if (partList.get(0).getPartPrice() == null) {
                    bean.setPartPrice(BigDecimal.ZERO);
                } else {
                    bean.setPartPrice(partList.get(0).getPartPrice());
                }
                bean.setPartNum(partList.get(0).getPartNum());
                // 新增【维修记录表】
                repairMapper.addRecord(bean);
            }

            // 配件费用计算
            sfCosts = countPartCosts(partList, sfCosts);

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

    /**
     * 校验维修数量
     */
    private static BigDecimal verifyRepairNum(RepairApplyRecord bean, RepairTaskDetails details) {
        if (bean == null || bean.getRepairNum() == null) {
            throw new ServiceException("维修数量不能为空");
        }
        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 i = repairedNum.add(bean.getRepairedNum());
            repairMapper.updateRepairedNumTwo(bean.getId(), i, loginUser.getUserid());
        }

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

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

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

        for (RepairDeviceVO bean : repairDeviceVOList) {
            if (bean.getManageType() == null) {
                throw new ServiceException("请选择物资管理方式");
            }
            if (Objects.equals(MaTypeManageTypeEnum.CODE_DEVICE.getTypeId(), bean.getManageType())) {
                // 物资管理方式--编码管理
                if (bean.getRepairType() == null) {
                    continue;
                }
                // 根据维修方式，更新维修数量、报废数量
                switch (bean.getRepairType()) {
                    case INNER_REPAIR: {
                        partList = bean.getCodeInRepairPartList();
                        // 更新维修数量、并修改维修人员
                        repairMapper.updateRepairedNumAndStatus(bean.getId(), BigDecimal.ZERO, 1, loginUser.getUserid(), loginUser.getUserid());
                        break;
                    }
                    case RETURN_FACTORY: {
                        partList = bean.getCodeOutRepairPartList();
                        // 更新维修数量、维修人员不变
                        repairMapper.updateRepairedNumTwoAndStatus(bean.getId(), BigDecimal.ZERO, 1, loginUser.getUserid());
                        break;
                    }
                    case TO_SCRAP: {
                        // 报废无需上传配件、直接初始化空集合
                        partList = bean.getCodeScrapRepairPartList();
                        // 更新报废数量
                        repairMapper.updateScrapNumAndStatus(bean.getId(), BigDecimal.ZERO, 1, loginUser.getUserid());
                        break;
                    }
                    default:
                        System.err.println("请输入正确的维修类型:" + bean.getRepairType());
                        break;
                }
                // 统一处理配件集合数据
                copeNumberManageInList(bean, partList, loginUser, bean.getManageType());

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

                BigDecimal innerRepairNum = BigDecimal.ZERO;
                BigDecimal outerRepairNum = BigDecimal.ZERO;
                BigDecimal scrapNum = BigDecimal.ZERO;

                // 处理配件--数量管理--内部维修
                if (CollectionUtil.isNotEmpty(bean.getNumberInRepairPartList())) {
                    partList = bean.getNumberInRepairPartList();
                    if (partList.get(0).getRepairNum() != null && partList.get(0).getRepairNum().compareTo(BigDecimal.ZERO) > 0 ) {
                        // 获取维修详情表中的维修详情记录：待维修、已维修、已报废的数量
                        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.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 (partList.get(0).getRepairNum() != null && partList.get(0).getRepairNum().compareTo(BigDecimal.ZERO) > 0) {
                        // 分拆维修单, 准备数据
                        outerRepairNum = partList.get(0).getRepairNum();

                        if (partList.get(0).getSupplierId() == null) {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.getUsername());

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

                        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())
                                        .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(fileInfo.getId() == null ? "" : String.valueOf(fileInfo.getId()))
                                        .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);
                            }
                        } 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 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("本次维修提交总数过大");
        }
        //本次修完了
        if ((bean.getRepairNum().subtract(innerRepairNum).subtract(outerRepairNum).subtract(scrapNum).compareTo(BigDecimal.valueOf(0)) ) == 0) {
            repairMapper.updateRepairedNum(bean.getId(), innerRepairNum.add(outerRepairNum) , loginUser.getUserid(), loginUser.getUserid());
            repairMapper.updateScrapNum(bean.getId(), scrapNum, loginUser.getUserid());
        } else {
            repairMapper.updateRepairedNum(bean.getId(), innerRepairNum.add(outerRepairNum) , loginUser.getUserid(), loginUser.getUserid());
            repairMapper.updateScrapNum(bean.getId(), scrapNum, loginUser.getUserid());
//            repairMapper.updateThisRepairedAndScrapNum(bean.getId(), innerRepairNum.add(outerRepairNum), scrapNum, loginUser.getUserid(), loginUser.getUserid());
        }
    }


    /**
     * 配件列表价格合计
     * @param partList 配件列表
     * @param sfCosts 配件价格合计
     * @return 配件合计后的价格
     */
    private static BigDecimal countPartCosts(List<RepairPartDetails> partList, BigDecimal sfCosts) {
        for (RepairPartDetails partDetails : partList) {
            if (partDetails.getPartPrice() != null && partDetails.getPartNum() != null) {
                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 (bean.getManageType() == null) {
                throw new ServiceException("请选择物资管理方式");
            }
            // 如果是数量管理，那么默认为内部维修
            if (bean.getRepairType() == null && MaTypeManageTypeEnum.NUMBER_DEVICE.getTypeId().equals(manageType)) {
                bean.setRepairType(RepairTypeEnum.INNER_REPAIR.getTypeId());
            }
            // 再检查还是null的话直接结束任务
            if (bean.getRepairType() == null) {
                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.getUsername());
                    repairApplyRecord.setStatus(0L);

                    if (partDetails.getPartId() != null && partDetails.getPartNum() != null) {
                        // 有维修配件时,如果价格为空，设置为0
                        if (partDetails.getPartCost() == null) {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);
                    } else {
                        // 不选维修配件时, 只添加【维修记录表】
                        repairMapper.addRecord(repairApplyRecord);
                    }
                }

                BigDecimal sfCosts = countPartCosts(partList, BigDecimal.ZERO);
                // TODO: 判断是否是收费配件，因数据存在多条，可能有些是免费配件 有些收费，所以这里用价格统一做处理，后续讨论
                // SQL: 新增【维修费用记录表】
                repairMapper.addRepairCost(repairApplyRecord, sfCosts, sfCosts.equals(BigDecimal.ZERO) ? "0" : "1");
            }

            // 外部维修
            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());

                // 编码管理--外部返厂维修
                RepairApplyRecord repairApplyRecord = new RepairApplyRecord().setId(bean.getId()).setTaskId(bean.getTaskId()).setMaId(bean.getMaId())
                        .setTypeId(bean.getTypeId()).setRepairType(RepairTypeEnum.RETURN_FACTORY.getTypeId())
                        .setPartName(partList.get(0).getPartName())
                        .setPartType(partList.get(0).getPartType())
                        .setRepairContent(partList.get(0).getRepairContent()).setPartNum(partList.get(0).getPartNum());

                if (partList.get(0).getSupplierId() == null) {
                    throw new ServiceException("请选择返厂厂家");
                }
                repairApplyRecord.setSupplierId(partList.get(0).getSupplierId());
                repairApplyRecord.setPartPrice(Optional.ofNullable(partList.get(0).getPartPrice()).orElse(BigDecimal.ZERO));
                // 新增【维修记录表】
                repairMapper.addRecord(repairApplyRecord);

                // 配件费用计算
                BigDecimal sfCosts = countPartCosts(partList, BigDecimal.ZERO);

                // TODO: 判断是否是收费配件，因数据存在多条，可能有些是免费配件 有些收费，所以这里用价格统一做处理，后续讨论
                // SQL: 新增【维修费用记录表】
                repairMapper.addRepairCost(repairApplyRecord, sfCosts, sfCosts.equals(BigDecimal.ZERO) ? "0" : "1");
            }

            // 如果是报废类型，进行上传附件相关处理
            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())
                                .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());

                        // 不选维修配件时, 只添加【维修记录表】
                        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());

                    // 不选维修配件时, 只添加【维修记录表】
                    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());

            // 不选维修配件时, 只添加【维修记录表】
            repairMapper.addRecord(repairApplyRecord);
        }
    }

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

        // 1.查询选择任务是否还有未完成维修的数据
        for (RepairTask task : taskList) {
            if (repairMapper.getUnFinish(task) == 0) {
                repairMapper.updateSingleTaskStatus(task, loginUser.getUserid(), RepairTaskStatusEnum.TASK_STATUS_COMPLETE.getStatus());
            }
        }

        // 3.业务逻辑处理
        for (RepairTask task : taskList) {
            // 查询维修任务的详情表
            Long oldWxTaskId = task.getTaskId();
            List<RepairTaskDetails> detailsList = repairApplyDetailsMapper.getRepairDetailsWhichNotSent(oldWxTaskId);
            BigDecimal thisRepairedNum = detailsList.stream().map(RepairTaskDetails::getThisRepairedNum).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal thisScrapNum = detailsList.stream().map(RepairTaskDetails::getThisScrapNum).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (!CollectionUtils.isEmpty(detailsList) && (thisRepairedNum.add(thisScrapNum)).compareTo(BigDecimal.valueOf(0)) > 0) {
                task.setCreateBy(loginUser.getUserid());
                Long agreementId = repairMapper.getAgreementId(task);
                // 新增tm_task表数据、修饰审核任务、状态是待审核
                task.setTaskType(TmTaskTypeEnum.TM_TASK_REPAIR_AUDIT.getTaskTypeId());
                task.setTaskStatus(RepairTaskStatusEnum.TASK_STATUS_TO_EXAM.getStatus());
                task.setRepairCode(detailsList.get(0).getTaskCode());
                repairMapper.addTask(task); // 注意：此处将会生成新的 taskId （审核入库用的）
                // 新增协议任务表tm_task_agreement--关联修饰任务与协议
                task.setAgreementId(agreementId);
                repairMapper.createAgreementTask(task);

                // 新增审计记录
                for (RepairTaskDetails details : detailsList) {
                    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));
                    repairApplyDetailsMapper.updateRepairApplyDetails(repairApplyDetails);
                    details.setCreateBy(String.valueOf(loginUser.getUserid()));
                    details.setTaskId(task.getTaskId());
                    details.setRepairNum(details.getThisRepairedNum().add(details.getThisScrapNum()) );
                    details.setRepairedNum(details.getThisRepairedNum());
                    details.setScrapNum(details.getThisScrapNum());
                    repairMapper.addAuditDetails(details);
                }
            }
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult rejectRepair(@NotNull List<Long> taskList) {
        try {
            taskList.forEach(taskId -> taskMapper.updateTaskStatus(String.valueOf(taskId), RepairTaskStatusEnum.TASK_STATUS_REJECT.getStatus()));
        } catch (DataAccessException e) {
            System.err.println(e.getMessage());
            return AjaxResult.error("数据库SQL修改执行失败" + e.getMessage());
        }
        return AjaxResult.success("执行完成");
    }

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

    @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;
    }
}
