package cn.ezhizao.project.business.controller;

import cn.ezhizao.common.utils.PdfUtil;
import cn.ezhizao.common.utils.poi.ExcelUtil;
import cn.ezhizao.framework.aspectj.lang.annotation.Log;
import cn.ezhizao.framework.aspectj.lang.enums.BusinessType;
import cn.ezhizao.framework.redis.RedisCache;
import cn.ezhizao.framework.web.controller.BaseController;
import cn.ezhizao.framework.web.domain.AjaxResult;
import cn.ezhizao.framework.web.page.TableDataInfo;
import cn.ezhizao.project.business.domain.*;
import cn.ezhizao.project.business.service.*;
import cn.hutool.extra.template.TemplateException;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 收回单主表
 *
 * @author 庄德政
 * date    2024-04-26
 */
@RestController
@RequestMapping("/business/returnReceipt")
public class BizReturnReceiptController extends BaseController {
    @Resource
    private IBizReturnReceiptService bizReturnReceiptService;
    @Resource
    private IBizReturnReceiptDetailService bizReturnReceiptDetailService;
    @Resource
    private IBizOutsourcedOrderDetailProcessService bizOutsourcedOrderDetailProcessService;
    @Resource
    private IBizOutsourcedOrderDetailService bizOutsourcedOrderDetailService;
    @Resource
    private IBizSupplierService bizSupplierService;
    @Resource
    private IBizCarrierService bizCarrierService;
    @Resource
    private IBizCarrierCategoryService bizCarrierCategoryService;
    @Resource
    private IBizDayworkService bizDayworkService;
    @Resource
    private RedisCache redisCache;
    @Resource
    HttpServletRequest request;
    @Resource
    private IBizDayworkCarrierService bizDayworkCarrierService;

    /**
     * 生成pdf
     */
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    /**
     * 查询收回单主
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:list')")
    @Log(title = "外协收回单查询", businessType = BusinessType.SELECT)
    @GetMapping("/list")
    public TableDataInfo list(BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException {
        if (bizReturnReceipt.getStartTime() != null) {
            bizReturnReceipt.setStartTime(bizReturnReceipt.getStartTime() + " 00:00:00");
        }
        if (bizReturnReceipt.getEndTime() != null) {
            bizReturnReceipt.setEndTime(bizReturnReceipt.getEndTime() + " 23:59:59");
        }
        final String supplierId = request.getHeader("tenantId");
        bizReturnReceipt.setSupplierId(Long.parseLong(supplierId));
        startPage();
        List<BizReturnReceipt> list = bizReturnReceiptService.getList(bizReturnReceipt);
        return getDataTable(list);
    }

    /**
     * 导出收回单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子列表
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:export')")
    @Log(title = "收回单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException, IOException {
        bizReturnReceipt = bizReturnReceiptService.getById(bizReturnReceipt);
        BizSupplier supplier = bizSupplierService.query().eq("id", bizReturnReceipt.getSupplierId()).list().get(0);
        bizReturnReceipt.setSupplierCode(supplier.getCode());
        List<BizReturnReceiptDetail> returnReceiptDetailList = bizReturnReceiptDetailService.query().eq("master_id", bizReturnReceipt.getId()).orderByAsc("process_step_number").list();
        //按照批次分组，一个批次合并成一条
        List<String> lotCodeList = returnReceiptDetailList.stream()
                .map(BizReturnReceiptDetail::getLotCode)
                .distinct()
                .collect(Collectors.toList());
        Map<String, List<BizReturnReceiptDetail>> groupedByLotCode = new LinkedHashMap<>();
        for (String lotCode : lotCodeList) {
            groupedByLotCode.put(lotCode, returnReceiptDetailList.stream()
                    .filter(record -> record.getLotCode().equals(lotCode))
                    .sorted(Comparator.comparing(BizReturnReceiptDetail::getProcessStepNumber))
                    .collect(Collectors.toList()));
        }
        List<BizReturnReceiptDetail> details = new ArrayList<>();
        for (Map.Entry<String, List<BizReturnReceiptDetail>> entry : groupedByLotCode.entrySet()) {
            BizReturnReceiptDetail info = new BizReturnReceiptDetail();
            String lotCode = entry.getKey();
            List<BizReturnReceiptDetail> detailList = entry.getValue();
            info.setProductDescription(detailList.get(0).getProductDescription());
            info.setOutsourceDetailId(detailList.get(0).getOutsourceDetailId());
            info.setLotCode(lotCode);
            info.setReceiptNum(detailList.get(detailList.size() - 1).getReceiptNum());
            info.setNewCarrier(detailList.get(0).getNewCarrier());
            info.setNewCarrierCount(detailList.get(0).getNewCarrierCount());
            info.setRemark(detailList.get(0).getRemark());
            details.add(info);
        }
        bizReturnReceipt.setDetails(details);
        bizReturnReceiptService.exportTemplateProvinceAreaData(response, bizReturnReceipt);
    }

    @Log(title = "修改外协收回单提交状态", businessType = BusinessType.UPDATE)
    @PutMapping("/updateReceiptSubmitStatus")
    public AjaxResult updateReceiptSubmitStatus(@RequestBody BizReturnReceipt bizReturnReceipt) {
        BizReturnReceipt returnReceipt = bizReturnReceiptService.query().eq("id", bizReturnReceipt.getId()).one();
        returnReceipt.setIsSubmit(0);
        bizReturnReceiptService.updateById(returnReceipt);
        return success();
    }

    /**
     * 新增外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:add')")
    @Log(title = "外协收回单新增", businessType = BusinessType.UPDATE)
    @Transactional
    @PostMapping
    public AjaxResult addReceipt(@RequestBody BizReturnReceipt bizReturnReceipt) {
        final String supplierId = request.getHeader("tenantId");
        bizReturnReceipt.setSupplierId(Long.parseLong(supplierId));
        //若有id，则说将之前的明细删除不生成新的单号
        if (bizReturnReceipt.getId() != null) {
            List<Long> ids = new ArrayList<>();
        } else {
            /* 生成单号 */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yy"); // 定义日期格式
            String formattedDate = dateFormat.format(new Date());
            String codeValue;
            String codeType = "returnReceiveCode";
            //查询redis中外协单号的值
            String previous = redisCache.hasKey(codeType) ? redisCache.getCacheObject(codeType) : "";
            //若不存在，则直接存入
            if (previous.isEmpty()) {
                List<BizReturnReceipt> returnReceiptList = bizReturnReceiptService.getAllList();
                if (!returnReceiptList.isEmpty()) {
                    codeValue = returnReceiptList.get(0).getFormCode();
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                } else {
                    previous = ("SHD" + formattedDate + "000001");
                }
            } else {
                codeValue = previous;
                String codeYear = codeValue.substring(3, 5);//取出当前外协单号年份
                //如果年份一致表示是当前年的发出单，如果不一致则表示已经进入了新的一年则重置发出单号
                if (codeYear.equals(formattedDate)) {
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                } else {
                    previous = ("SHD" + formattedDate + "00001");
                }
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizReturnReceipt.setFormCode(previous);
        }
        //向收回单主表存
        bizReturnReceiptService.save(bizReturnReceipt);
        //向收回单明细表存
//        bizReturnReceipt.getDetails().stream()
//                .forEach(bizReturnReceiptDetail -> {
//                    bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
//                    bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
//                    bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
//                    bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
//                    bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
//                });
        bizReturnReceipt.getDetailInfo().stream()
                .forEach(bizReturnReceiptDetail -> {
                    bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
                    bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
                    bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
                    bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
                    bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
                });
//        return success(bizReturnReceiptDetailService.saveBatch(bizReturnReceipt.getDetails()));
        return success(bizReturnReceiptDetailService.saveBatch(bizReturnReceipt.getDetailInfo()));
    }

    /**
     * 修改外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:edit')")
    @Log(title = "外协收回单修改", businessType = BusinessType.UPDATE)
    @Transactional
    @PutMapping
    public AjaxResult updateReceipt(@RequestBody BizReturnReceipt bizReturnReceipt) {
        //向收回单主表存
        bizReturnReceiptService.updateById(bizReturnReceipt);
        //向收回单明细表存
        List<BizReturnReceiptDetail> oldList = bizReturnReceiptDetailService.query().eq("master_id", bizReturnReceipt.getId()).list();
        bizReturnReceipt.getDetailInfo().stream()
                .forEach(bizReturnReceiptDetail -> {
                    bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
                    bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
                    bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
                    bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
                    bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
                });
        saveOrUpdateBatch(bizReturnReceiptDetailService, bizReturnReceipt.getDetailInfo(), oldList);
//        bizReturnReceipt.getDetails().stream()
//                .forEach(bizReturnReceiptDetail -> {
//                    bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
//                    bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
//                    bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
//                    bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
//                    bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
//                });
//        saveOrUpdateBatch(bizReturnReceiptDetailService,bizReturnReceipt.getDetails(),oldList);
        return success();
    }

    /**
     * 获取收回单主 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子详细信息
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:query')")
    @Log(title = "外协收回单查询详细信息", businessType = BusinessType.SELECT)
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        // 根据 id 获取到收回订单
        BizReturnReceipt returnReceipt = bizReturnReceiptService.getById(id);

        // 根据收回订单id，获取到该收回订单的所有明细
        List<BizReturnReceiptDetail> returnReceiptDetails = bizReturnReceiptDetailService.query()
                .eq("master_id", id)
                .list();
        List<BizDayworkCarrier> carriers = bizDayworkCarrierService.query().eq("is_changed", 0).in("daywork_id", returnReceiptDetails.stream().map(BizReturnReceiptDetail::getDayworkId).collect(Collectors.toList())).list();
        returnReceiptDetails.forEach(item -> {
            item.setUnbind(carriers.stream().anyMatch(t -> t.getDayworkId().equals(item.getDayworkId())) ? 0 : 1);
        });

        // 将得到的收回明细的id，组合成一个集合，用于查询这个订单下的，所有收回出来的工序，
        // 这里得到的工序清单，是混合的，并没有根据各自对应的明细，进行分组，仅仅是获取全部，为后续分组做准备
        List<Long> detailIds = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getOutsourceDetailId)
                .collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> detailProcesses = bizOutsourcedOrderDetailProcessService.query()
                .in("detail_id", detailIds)
                .orderByAsc(Arrays.asList("detail_id", "process_step_number"))
                .list();
        //按照批次分组，一个批次合并成一条
        List<String> lotCodeList = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getLotCode)
                .distinct()
                .collect(Collectors.toList());
        Map<String, List<BizReturnReceiptDetail>> groupedByLotCode = new LinkedHashMap<>();
        for (String lotCode : lotCodeList) {
            groupedByLotCode.put(lotCode, returnReceiptDetails.stream()
                    .filter(record -> record.getLotCode().equals(lotCode))
                    .sorted(Comparator.comparing(BizReturnReceiptDetail::getProcessStepNumber))
                    .collect(Collectors.toList()));
        }
        List<BizReturnReceiptDetail> details = new ArrayList<>();
        for (Map.Entry<String, List<BizReturnReceiptDetail>> entry : groupedByLotCode.entrySet()) {
            BizReturnReceiptDetail info = new BizReturnReceiptDetail();
            String lotCode = entry.getKey();
            List<BizReturnReceiptDetail> detailList = entry.getValue();
            info.setProductDescription(detailList.get(0).getProductDescription());
            info.setOutsourceDetailId(detailList.get(0).getOutsourceDetailId());
            info.setLotCode(lotCode);
            info.setProductNum(detailList.get(0).getProductNum());
            info.setReceiptNum(detailList.get(detailList.size() - 1).getReceiptNum());
            info.setNewCarrier(detailList.get(0).getNewCarrier());
            info.setRemark(detailList.get(0).getRemark());
            info.setUnbind(detailList.get(0).getUnbind());
            info.setProcessAlias(detailProcesses.stream()
                    .filter(dp -> dp.getDetailId().equals(detailList.get(0).getOutsourceDetailId()))
                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
                    .collect(Collectors.joining("，")));
            details.add(info);
        }
//        // 遍历明细，将对应的工序，与订单明细进行匹配
//        returnReceiptDetails.forEach(item -> {
//            // 根据明细的id，获取到该明细对应的收回工序，并将得到的工序，组成中文逗号分割的字符串
//            String processNames = detailProcesses.stream()
//                    .filter(dp -> dp.getDetailId().equals(item.getOutsourceDetailId()))
//                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
//                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
//                    .collect(Collectors.joining("，"));
//
//            item.setProcessNames(processNames);
//        });

        // 将收回明细赋值给收回订单
        returnReceipt.setDetailInfo(returnReceiptDetails);
        returnReceipt.setDetails(details);


        return success(returnReceipt);
    }

    /**
     * 删除外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:remove')")
    @Log(title = "外协收回单删除", businessType = BusinessType.DELETE)
    @Transactional
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids) {
        bizReturnReceiptService.removeBatchByIds(ids);
        List<BizReturnReceiptDetail> bizReturnReceiptDetailList = bizReturnReceiptDetailService.query().in("master_id", ids).list();
        List<Long> bizReturnReceiptDetailIds = bizReturnReceiptDetailList.stream().map(BizReturnReceiptDetail::getId).collect(Collectors.toList());
        return toAjax(bizReturnReceiptDetailService.removeBatchByIds(bizReturnReceiptDetailIds));
    }


    @Log(title = "外协打印", businessType = BusinessType.EXPORT)
    @PostMapping("/printDetailPdf")
    public void SocialSecurityPdf(BizReturnReceipt bizReturnReceipt, HttpServletResponse response) throws IOException, TemplateException, freemarker.template.TemplateException {

        /** 正常打印 **/
        //查询回收单数据
        bizReturnReceipt = bizReturnReceiptService.getById(bizReturnReceipt);
        BizSupplier supplier = bizSupplierService.query().eq("id", bizReturnReceipt.getSupplierId()).list().get(0);
        bizReturnReceipt.setSupplierCode(supplier.getCode());
        //查询回收单明细
//        List<BizReturnReceiptDetail> detailList=bizReturnReceiptDetailService.query().in("master_id", bizReturnReceipt.getId()).list();
        // 根据收回订单id，获取到该收回订单的所有明细
//        List<BizReturnReceiptDetail> returnReceiptDetails = bizReturnReceiptDetailService.query()
//                .eq("master_id", bizReturnReceipt.getId())
//                .list();

        List<BizReturnReceiptDetail> returnReceiptDetails = bizReturnReceiptDetailService.getListByReceiptId(bizReturnReceipt.getId());


        // 创建SimpleDateFormat对象，并设置日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        bizReturnReceipt.setStringDate(dateFormat.format(bizReturnReceipt.getFormDate()));

        // 将得到的收回明细的id，组合成一个集合，用于查询这个订单下的，所有收回出来的工序，
        // 这里得到的工序清单，是混合的，并没有根据各自对应的明细，进行分组，仅仅是获取全部，为后续分组做准备
        List<Long> detailIds = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getOutsourceDetailId)
                .collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> detailProcesses = bizOutsourcedOrderDetailProcessService.query()
                .in("detail_id", detailIds)
                .orderByAsc(Arrays.asList("detail_id", "process_step_number"))
                .list();

        // 遍历明细，将对应的工序，与订单明细进行匹配
        returnReceiptDetails.forEach(item -> {
            // 根据明细的id，获取到该明细对应的收回工序，并将得到的工序，组成中文逗号分割的字符串
            String processNames = detailProcesses.stream()
                    .filter(dp -> dp.getDetailId().equals(item.getOutsourceDetailId()))
                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
                    .collect(Collectors.joining("，"));

            item.setProcessNames(processNames);
        });

        List<String> lotCodeList = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getLotCode)
                .distinct()
                .collect(Collectors.toList());

        // 使用List.sort()对lotCodeList进行升序排序
        lotCodeList.sort(String::compareTo);

        Map<String, List<BizReturnReceiptDetail>> groupedByLotCode = new LinkedHashMap<>();

        for (String lotCode : lotCodeList) {
            groupedByLotCode.put(lotCode, returnReceiptDetails.stream()
                    .filter(record -> record.getLotCode().equals(lotCode))
                    .sorted(Comparator.comparing(BizReturnReceiptDetail::getProcessStepNumber))
                    .collect(Collectors.toList()));
        }
        List<BizReturnReceiptDetail> allDetailsStream = groupedByLotCode.values().stream()
                .map(list -> list.isEmpty() ? null : list.get(list.size() - 1)) // 获取每个List的最后一个元素，如果List为空，则返回null
                .filter(Objects::nonNull) // 过滤掉null值
                .collect(Collectors.toList()); // 收集到一个新的List中

        // 使用 Stream API 按照 productDescription 属性进行分组，
        // 并将每个分组的元素收集到一个 List 中
        Map<String, List<BizReturnReceiptDetail>> groupedByProductDescription =
                allDetailsStream.stream()
                        .collect(Collectors.groupingBy(
                                BizReturnReceiptDetail::getProductDescription, // 分组依据的函数
                                Collectors.toList() // 指定分组内的元素收集为 List
                        ));


        //因为新箱子保存的时候，是用“id|code,id|code”的字符串形式存储的所以查询的时候需要进行拆分
        //如果保存的时候没有选择新箱子则会把旧箱号复制到新箱号中，所有不会有“|”所以下方需要进行判断
        allDetailsStream.forEach(detail -> {
            // 因为需要显示箱号，所以需要拆分出code重新拼接到NewCarrier
            List<String> codeList = new ArrayList<>();
            //使用 StringTokenizer 来分割字符串
            StringTokenizer tokenizer = new StringTokenizer(detail.getNewCarrier(), ",");
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                // 检查当前 token 是否包含 "|" 字符 如果没有表示不是新箱，则跳过当前 token
                if (token.contains("|")) {
                    String[] idCode = token.split("\\|"); // 安全地分割 token
                    if (idCode.length == 2) {
                        codeList.add(idCode[1]);
                        BizCarrier bizCarrier = new BizCarrier();
                        bizCarrier.setId(Long.parseLong(idCode[0]));
                        bizCarrier.setCode(idCode[1]);
                    }
                }
            }
            if (!codeList.isEmpty()) {
                detail.setNewCarrier(String.join(",", codeList));
            }

        });

        List<List<BizReturnReceiptDetail>> list = new ArrayList<>();

        // 使用 for-each 循环遍历 groupedByProductDescription
        for (Map.Entry<String, List<BizReturnReceiptDetail>> entry : groupedByProductDescription.entrySet()) {
            List<BizReturnReceiptDetail> details = entry.getValue(); // 获取对应的 List，即 Map 的值
            // 用于临时存储每组数据的列表
            List<BizReturnReceiptDetail> group = new ArrayList<>();
            // 遍历 outsourcedOrderDetails 列表
            for (BizReturnReceiptDetail detail : details) {
                group.add(detail);
                // 每添加 14 个元素后，将其添加到 list 中，并重置 group
                if (group.size() == 14) {
                    list.add(new ArrayList<>(group));
                    group = new ArrayList<>();
                }
            }
            // 如果最后一组不足 14 个元素，也将其添加到 list 中
            if (!group.isEmpty()) {
                BizReturnReceiptDetail orderDetail = new BizReturnReceiptDetail();
                while (group.size() < 14) {
                    group.add(orderDetail); // 添加默认元素直到总数为14
                }
                list.add(group);
            }
        }
        for (List<BizReturnReceiptDetail> listItem : list) {
            // 使用流过滤出 getReceiptNum 不为空的元素，并对其 productNum 值求和
            Integer sum = listItem.stream()
                    .filter(item -> item.getReceiptNum() != null) // 过滤出 productNum 不为空的元素
                    .mapToInt(BizReturnReceiptDetail::getReceiptNum) // 映射到 productNum 属性
                    .sum(); // 计算总和
            // 然后，给每个对象的 sum 属性赋值
            for (BizReturnReceiptDetail item : listItem) {
                item.setSum(sum);
                item.setOriginalCarrierCount(item.getNewCarrierCount() != null && item.getNewCarrierCount() != 0 ? item.getNewCarrierCount() : item.getOriginalCarrierCount());
            }


        }
//         2024-11-22注释  修改为同发出单一致的逻辑
//        //查询外协厂code
//        BizSupplier supplier=bizSupplierService.getById(bizReturnReceipt.getSupplierId());
//        bizReturnReceipt.setSupplierCode(supplier.getCode());
//
//        // 创建SimpleDateFormat对象，并设置日期格式
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//        bizReturnReceipt.setStringDate(dateFormat.format(bizReturnReceipt.getFormDate()));
//
//        List<List<BizReturnReceiptDetail> > list = new ArrayList<>();
//
//        //打印数据时每页14条
//        if(returnReceiptDetails.size() > 14){
//            // 用于临时存储每组数据的列表
//            List<BizReturnReceiptDetail> group = new ArrayList<>();
//            // 遍历 outsourcedOrderDetails 列表
//            for (BizReturnReceiptDetail detail : returnReceiptDetails) {
//                group.add(detail);
//                // 每添加 14 个元素后，将其添加到 list 中，并重置 group
//                if (group.size() == 14) {
//                    // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
//                    Integer sum = group.stream()
//                            .filter(item -> item.getProductNum() != null) // 过滤出 productNum 不为空的元素
//                            .mapToInt(BizReturnReceiptDetail::getProductNum) // 映射到 productNum 属性
//                            .sum(); // 计算总和
//                    // 然后，给每个对象的 sum 属性赋值
//                    for (BizReturnReceiptDetail item : group) {
//                        item.setSum(sum);
//                        item.setOriginalCarrierCount(item.getNewCarrierCount()==null?item.getOriginalCarrierCount():item.getNewCarrierCount());
//                    }
//                    list.add(new ArrayList<>(group));
//                    group = new ArrayList<>();
//                }
//
//            }
//            // 如果最后一组不足 14 个元素，也将其添加到 list 中
//            if (!group.isEmpty()) {
//                BizReturnReceiptDetail detail=new BizReturnReceiptDetail();
//                while (group.size() < 14) {
//                    group.add(detail); // 添加默认元素直到总数为14
//                }
//                // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
//                Integer sum = group.stream()
//                        .filter(item -> item.getReceiptNum() != null) // 过滤出 productNum 不为空的元素
//                        .mapToInt(BizReturnReceiptDetail::getReceiptNum) // 映射到 productNum 属性
//                        .sum(); // 计算总和
//                // 然后，给每个对象的 sum 属性赋值
//                for (BizReturnReceiptDetail receiptDetail : group) {
//                    receiptDetail.setSum(sum);
//                    receiptDetail.setOriginalCarrierCount(receiptDetail.getNewCarrierCount()==null?receiptDetail.getOriginalCarrierCount():receiptDetail.getNewCarrierCount());
//                }
//                list.add(group);
//            }
//
//        }else{
//            BizReturnReceiptDetail detail=new BizReturnReceiptDetail();
//            while (returnReceiptDetails.size() < 14) {
//                returnReceiptDetails.add(detail); // 添加默认元素直到总数为14
//            }
//            // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
//            Integer sum = returnReceiptDetails.stream()
//                    .filter(item -> item.getReceiptNum() != null) // 过滤出 productNum 不为空的元素
//                    .mapToInt(BizReturnReceiptDetail::getReceiptNum) // 映射到 productNum 属性
//                    .sum(); // 计算总和
//            // 然后，给每个对象的 sum 属性赋值
//            for (BizReturnReceiptDetail receiptDetail : returnReceiptDetails) {
//                receiptDetail.setSum(sum);
//                receiptDetail.setOriginalCarrierCount(receiptDetail.getNewCarrierCount()==null?receiptDetail.getOriginalCarrierCount():receiptDetail.getNewCarrierCount());
//            }
//
//            list.add(returnReceiptDetails);
//        }

        bizReturnReceipt.setDetailLists(list);


        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("returnReceipt", bizReturnReceipt);
        Writer out = new StringWriter();
        //获取模板地址
        Template template = freeMarkerConfigurer.getConfiguration().getTemplate("returnReceiptPdf.html");
        template.process(paramMap, out);
        out.flush();
        out.close();
        String templateContent = out.toString();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/pdf");
        String fileName = "外协收回明细";
        response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes()));
        byte[] resources = PdfUtil.html2Pdf(templateContent);
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(resources);
        outputStream.close();
    }


    @Log(title = "按炉结算检测", businessType = BusinessType.SELECT)
    @Transactional
    @PostMapping("/checkFurnace")
    public AjaxResult checkFurnace(@RequestBody List<BizReturnReceiptDetail> details) {
        // 判断明细中有没有按炉结算的明细
        // 判断按炉结算的明细的发出单明细是否都包含在明细内
        List<BizOutsourcedOrderDetail> orderDetails = bizOutsourcedOrderDetailService.query().in("id", details.isEmpty() ? Collections.singletonList(0L) : details.stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList())).eq("settlement_type", "2").list();
        List<BizOutsourcedOrderDetail> allOrderDetails = bizOutsourcedOrderDetailService.query().in("master_id", orderDetails.isEmpty() ? Collections.singletonList(0L) : orderDetails.stream().map(BizOutsourcedOrderDetail::getMasterId).collect(Collectors.toList())).list();
        if (allOrderDetails.isEmpty()) {
            return success(true);
        } else if (allOrderDetails.stream().allMatch(v -> details.stream().anyMatch(e -> e.getOutsourceDetailId().equals(v.getId())))) {
            return success(true);
        } else {
            // 返回信息 哪张外协发出单哪个批次没有包含进收回单
            List<BizOutsourcedOrderDetail> lackDetails = allOrderDetails.stream().filter(v -> details.stream().noneMatch(e -> e.getOutsourceDetailId().equals(v.getId()))).collect(Collectors.toList());
            Map<String, List<String>> messageSet = new HashMap<>();
            lackDetails.forEach(l -> {
                List<String> lotCodes = messageSet.get(l.getFormCode()) != null ? messageSet.get(l.getFormCode()) : new ArrayList<>();
                lotCodes.add(l.getLotCode());
                messageSet.put(l.getFormCode(), lotCodes);
            });
            AtomicReference<String> message = new AtomicReference<>("");
            messageSet.keySet().forEach(l -> {
                message.set(message + "发出单" + l + "中批次" + messageSet.get(l).stream().collect(Collectors.joining(",")) + "，");
//                        messageSet.get(l).stream().collect(Collectors.joining(","));
            });
            message.set(message + "未包含到收回单。");
            return AjaxResult.success(message.get(), false);
        }
    }

    @Log(title = "判断是否一箱多批", businessType = BusinessType.SELECT)
    @PostMapping("/checkAllowMore")
    public AjaxResult checkAllowMore(@RequestBody List<BizReturnReceiptDetail> details) {
        // 获取所有箱
        List<String> carrierCodes = new ArrayList<>();
        details.forEach(l -> {
            carrierCodes.addAll(Arrays.stream(l.getNewCarrier().split(",")).collect(Collectors.toList()));
        });
        List<BizCarrier> carriers = bizCarrierService.query().in("code", carrierCodes).list();
        List<BizCarrierCategory> bizCarrierCategories = bizCarrierCategoryService.query().in("id", carriers.isEmpty() ? Collections.singletonList(0L) : carriers.stream().map(BizCarrier::getCategoryId).collect(Collectors.toList())).list();
        // 没有一箱多批的箱子
        if (bizCarrierCategories.stream().noneMatch(v -> v.getIsAllowMore().equals(1))) {
            return success(true);
        }
        // 假设有一箱多批的箱子获取该箱子的所有报工
        List<BizDayworkCarrier> bizDayworkCarriers = bizDayworkCarrierService.query().in("carrier_id", carriers.stream().filter(e -> bizCarrierCategories.stream().filter(v -> v.getIsAllowMore().equals(1)).anyMatch(v -> v.getId().equals(e.getCategoryId()))).map(BizCarrier::getId).collect(Collectors.toList())).eq("is_changed", 0).list();
        List<BizDayworkCarrier> unreturn = bizDayworkCarriers.stream().filter(v -> details.stream().anyMatch(t -> t.getDayworkId().equals(v.getDayworkId()))).collect(Collectors.toList());
        List<BizDaywork> bizDayworks = bizDayworkService.query().in("id", unreturn.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList())).list();
        if (unreturn.size() > 0) {
            String msg = "周转箱" + unreturn.stream().map(BizDayworkCarrier::getCarrierCode).distinct().collect(Collectors.joining(",")) + "中批次" + bizDayworks.stream().map(BizDaywork::getLotCode).distinct().collect(Collectors.joining(",")) + "未收回";
            return AjaxResult.success(msg, false);
        }
        return success(true);
    }

    @Log(title = "获取内部外协详情")
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:query')")
    @GetMapping(value = "/interReceipt/{id}")
    public AjaxResult getInterInfo(@PathVariable("id") Long id) {
        // 根据 id 获取到收回订单
        BizReturnReceipt returnReceipt = bizReturnReceiptService.getById(id);

        // 根据收回订单id，获取到该收回订单的所有明细
        List<BizReturnReceiptDetail> returnReceiptDetails = bizReturnReceiptDetailService.getListByReceiptId(id);

        // 将得到的收回明细的id，组合成一个集合，用于查询这个订单下的，所有收回出来的工序，
        // 这里得到的工序清单，是混合的，并没有根据各自对应的明细，进行分组，仅仅是获取全部，为后续分组做准备
        List<Long> detailIds = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getOutsourceDetailId)
                .collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> detailProcesses = bizOutsourcedOrderDetailProcessService.query()
                .in("detail_id", detailIds)
                .orderByAsc(Arrays.asList("detail_id", "process_step_number"))
                .list();
        //按照批次分组，一个批次合并成一条
        List<String> lotCodeList = returnReceiptDetails.stream()
                .map(BizReturnReceiptDetail::getLotCode)
                .distinct()
                .collect(Collectors.toList());
        Map<String, List<BizReturnReceiptDetail>> groupedByLotCode = new LinkedHashMap<>();
        for (String lotCode : lotCodeList) {
            groupedByLotCode.put(lotCode, returnReceiptDetails.stream()
                    .filter(record -> record.getLotCode().equals(lotCode))
                    .sorted(Comparator.comparing(BizReturnReceiptDetail::getProcessStepNumber))
                    .collect(Collectors.toList()));
        }
        List<BizReturnReceiptDetail> details = new ArrayList<>();
        for (Map.Entry<String, List<BizReturnReceiptDetail>> entry : groupedByLotCode.entrySet()) {
            BizReturnReceiptDetail info = new BizReturnReceiptDetail();
            String lotCode = entry.getKey();
            List<BizReturnReceiptDetail> detailList = entry.getValue();
            info.setProductDescription(detailList.get(0).getProductDescription());
            info.setOutsourceDetailId(detailList.get(0).getOutsourceDetailId());
            info.setLotCode(lotCode);
            info.setProductNum(detailList.get(0).getProductNum());
            info.setReceiptNum(detailList.get(detailList.size() - 1).getReceiptNum());
            info.setNewCarrier(detailList.get(0).getNewCarrier());
            info.setRemark(detailList.get(0).getRemark());
            info.setProcessAlias(detailProcesses.stream()
                    .filter(dp -> dp.getDetailId().equals(detailList.get(0).getOutsourceDetailId()))
                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
                    .collect(Collectors.joining("，")));
            details.add(info);
        }
//        // 遍历明细，将对应的工序，与订单明细进行匹配
//        returnReceiptDetails.forEach(item -> {
//            // 根据明细的id，获取到该明细对应的收回工序，并将得到的工序，组成中文逗号分割的字符串
//            String processNames = detailProcesses.stream()
//                    .filter(dp -> dp.getDetailId().equals(item.getOutsourceDetailId()))
//                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
//                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
//                    .collect(Collectors.joining("，"));
//
//            item.setProcessNames(processNames);
//        });

        // 将收回明细赋值给收回订单
        returnReceipt.setDetailInfo(returnReceiptDetails);
        returnReceipt.setDetails(details);


        return success(returnReceipt);
    }
}
