package cn.ezhizao.project.business.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

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.security.LoginUser;
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.ezhizao.project.system.domain.SysDept;
import cn.ezhizao.project.system.service.ISysDeptService;
import cn.hutool.core.date.DateTime;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 外协单主
带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子Controller
 *
 * @author ezhizao
 * @date 2024-05-08
 */
@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 IBizDayworkItemService bizDayworkItemService;
    @Resource
    private IBizProcessInspecionService bizProcessInspecionService;
    @Resource
    private IBizCarrierService bizCarrierService;
    @Resource
    private IBizLotService bizLotService;
    @Resource
    private ISysDeptService deptService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private IBizOutsourceBalanceAccountService bizOutsourceBalanceAccountService;

    final private String processInspectionNoKey = "processInspectionCode";

    /**
     * 查询外协单主
带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子列表
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:list')")
    @GetMapping("/list")
    public TableDataInfo list(BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException
    {
        setTenantId(bizReturnReceipt);
        if(bizReturnReceipt.getStartTime()!=null) {
            bizReturnReceipt.setStartTime(bizReturnReceipt.getStartTime()+ " 00:00:00");
        }
        if(bizReturnReceipt.getEndTime()!=null) {
            bizReturnReceipt.setEndTime(bizReturnReceipt.getEndTime()+ " 23:59:59");
        }
        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
    {
        setTenantId(bizReturnReceipt);
        List<BizReturnReceipt> list = bizReturnReceiptService.getList(bizReturnReceipt);
        ExcelUtil<BizReturnReceipt> util = new ExcelUtil<BizReturnReceipt>(BizReturnReceipt.class);
        util.exportExcel(response, list, "外协单主 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子数据");
    }

    /**
     * 获取外协单主
带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子详细信息
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:query')")
    @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<Long> outsourceDetailIds = returnReceiptDetails.stream().map(BizReturnReceiptDetail::getOutsourceDetailId).distinct().collect(Collectors.toList());
        //查询是否有序检的数据
        List<BizProcessInspecion> processInspection = bizProcessInspecionService.query().in("outsource_order_detail_id", outsourceDetailIds.isEmpty() ? Collections.singletonList(0L) : outsourceDetailIds).list();
        List<BizOutsourcedOrderDetail> list = bizOutsourcedOrderDetailService.query().in("id", outsourceDetailIds).list();
        List<BizOutsourceBalanceAccount> balanceAccounts = bizOutsourceBalanceAccountService.query().eq("return_receipt_id", id).list();
        returnReceiptDetails.forEach(item -> {
            if(item.getIsAudit()==0) {
                item.setAuditNum(item.getReceiptNum());
            }
            BizOutsourceBalanceAccount bizOutsourceBalanceAccount = balanceAccounts.stream().filter(balanceAccount -> balanceAccount.getReturnReceiptDetailId().equals(item.getId())).findFirst().orElse(null);
            if (bizOutsourceBalanceAccount != null) {
                item.setIsProvedForCheck(1);
            }
            if (bizOutsourceBalanceAccount != null && bizOutsourceBalanceAccount.getStatus().equals(1)) {
                item.setIsCheckout(1);
            }
            list.forEach(info ->{
                if(item.getOutsourceDetailId().equals(info.getId())) {
                    item.setProductionDeptId(info.getProductionDeptId());
                }
            });
        });
        List<BizOutsourcedOrderDetailProcess> detailProcesses = bizOutsourcedOrderDetailProcessService.query()
                .in("detail_id", outsourceDetailIds)
                .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.setStatus(detailList.get(0).getStatus());
            info.setProductNum(detailList.get(0).getProductNum());
            info.setReceiptNum(detailList.get(detailList.size() -1).getReceiptNum());
            if(detailList.get(0).getIsAudit()==0) {
                info.setAuditNum(detailList.get(detailList.size() -1).getReceiptNum());
            }else {
                info.setAuditNum(detailList.get(detailList.size() -1).getAuditNum());
            }
            list.stream().forEach(item ->{
                if(info.getOutsourceDetailId().equals(item.getId())) {
                    info.setProductionDeptId(item.getProductionDeptId());
                }
            });
            info.setNewCarrier(detailList.get(0).getNewCarrier());
            info.setRemark(detailList.get(0).getRemark());
            info.setIsApproved(detailList.stream().allMatch(v -> v.getIsApproved() == 1) ? 1 : 0);
            info.setIsProvedForCheck(detailList.get(0).getIsProvedForCheck());
            info.setIsCheckout(detailList.get(0).getIsCheckout());
            info.setProcessAlias(detailProcesses.stream()
                    .filter(dp -> dp.getDetailId().equals(detailList.get(0).getOutsourceDetailId()))
                    .sorted(Comparator.comparing((BizOutsourcedOrderDetailProcess::getProcessStepNumber)))
                    .map(BizOutsourcedOrderDetailProcess::getProcessAlias)
                    .collect(Collectors.joining("，")));
            info.setProcessInspecionList(processInspection.stream().filter(pI -> pI.getOutsourceOrderDetailId().equals(info.getOutsourceDetailId())).collect(Collectors.toList()));
            details.add(info);
        }
//        // 将得到的收回明细的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);
//        });

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

    /**
     * 新增外协单主
带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:add')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.INSERT)
    @Transactional
//    @PostMapping("/new")
    @PostMapping
    public AjaxResult addNew(@RequestBody BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException, ParseException {
        // 判断是否有processes
        // 假设没有加个假的processes
        List<String> codes = new ArrayList<>();
        codes.add("27110");
        codes.add("28030");
        codes.add("28080");
        codes.add("27070");
        LoginUser user = getLoginUser();
        List<String> processCodes = bizReturnReceipt.getProcesses() == null ? codes : bizReturnReceipt.getProcesses();
        // 生成单据号
        // 若有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;
                int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                lastFourDigits += 1; // 加1
                codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                previous=codeValue;
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizReturnReceipt.setFormCode(previous);
        }
        bizReturnReceipt.setStatus(1);
        bizReturnReceipt.setIsSubmit(1);
        //向收回单主表存
        bizReturnReceiptService.save(bizReturnReceipt);
        // 获取载具们
        String carriers = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getNewCarrier).collect(Collectors.joining(","));
        List<String> carrierCodes = Arrays.stream(carriers.split(",")).collect(Collectors.toList());
        List<BizCarrier> carrierList = bizCarrierService.query().in("code", carrierCodes.isEmpty() ? Collections.singletonList("0") : carrierCodes).list();
        //将dayworkItem外协报工状态改成3,添加工时,审核数量设置成合格数
        List<Long> dayworkListIds = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getDayworkId).distinct().collect(Collectors.toList());
        //找到要修改的报工记录
        List<Long> outsourceDetailId = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getOutsourceDetailId).distinct().collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> bizOutsourcedOrderDetailProcess = bizOutsourcedOrderDetailProcessService.query().in("detail_id", outsourceDetailId).list();
        List<BizDayworkItem> dayworkItem = bizDayworkItemService.getListByDayworkIdsForOutsourced(dayworkListIds);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(simpleDateFormat.format(new Date()));
//        List<BizProcessInspecion> processInspecionList = new ArrayList<>();
        // 获取批次信息
        List<BizLot> bizLotList = bizLotService.query().in("id", dayworkItem.isEmpty() ? Collections.singletonList(0L) : dayworkItem.stream().map(BizDayworkItem::getLotId).collect(Collectors.toList())).list();
        //向收回单明细表存
        for(BizReturnReceiptDetail bizReturnReceiptDetail : bizReturnReceipt.getDetailInfo()) {
            bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
            bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
            bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
            bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
            bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
            bizReturnReceiptDetail.setIsAudit(1);
            bizReturnReceiptDetail.setIsApproved(processCodes.stream().noneMatch(e -> bizReturnReceiptDetail.getProcessCode().equals(e)) ? 1 : 0);
            for(BizDayworkItem item: dayworkItem) {
                for(BizOutsourcedOrderDetailProcess info: bizOutsourcedOrderDetailProcess) {
                    if (item.getDayworkId().equals(info.getDayworkId())&&item.getProcessStepNumber().equals(info.getProcessStepNumber())&& item.getLotId().equals(bizReturnReceiptDetail.getLotId())) {
                        item.setStatus("3");
                        item.setEndTime(date);
                        item.setNickName(bizReturnReceiptDetail.getSupplierName());
                        item.setQualifiedNum(bizReturnReceiptDetail.getAuditNum());
                        long timeDifference = date.getTime() - item.getStartTime().getTime();
                        item.setWorkingHours(timeDifference);
                    }
                    if (item.getDayworkId().equals(bizReturnReceiptDetail.getDayworkId()) && item.getProcessStepNumber().equals(bizReturnReceiptDetail.getProcessStepNumber())) {
                        bizReturnReceiptDetail.setProductionPlanDetailId(item.getProductionPlanDetailId());
                        bizReturnReceiptDetail.setDayworkItemId(item.getId());
                        bizReturnReceiptDetail.setCarriers(carrierList.stream().filter(v -> Arrays.stream(bizReturnReceiptDetail.getNewCarrier().split(",")).anyMatch(t -> v.getCode().equals(t))).collect(Collectors.toList()));
                    }
                }
            }
        }
        bizDayworkItemService.updateBatchById(dayworkItem);
//        bizProcessInspecionService.saveBatch(processInspecionList);
        // 新增所有的检查单
        bizReturnReceiptDetailService.saveBatch(bizReturnReceipt.getDetailInfo());
        addProcessInspection(bizReturnReceipt.getDetailInfo(), processCodes);
        return success();
    }

    private void addProcessInspection(List<BizReturnReceiptDetail> detailInfo, List<String> codes) {
        // detailInfo 是收回单明细 codes 是需要质检的所有工序明细
        // 对detailInfo 分组 同一发出单明细的分为一组
        Map<Long, List<BizReturnReceiptDetail>> groups = detailInfo.stream().collect(Collectors.groupingBy(BizReturnReceiptDetail::getOutsourceDetailId));
        List<BizProcessInspecion> bizProcessInspecions = bizProcessInspecionService.query().in("outsource_order_detail_id", detailInfo.isEmpty() ? Collections.singletonList(0L) : detailInfo.stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList())).list();
        List<BizProcessInspecion> removeItems = new ArrayList<>();
        List<BizProcessInspecion> saveItems = new ArrayList<>();
        List<BizOutsourcedOrderDetail> bizOutsourcedOrderDetails = bizOutsourcedOrderDetailService.query().in("id", detailInfo.isEmpty() ? Collections.singletonList(0L) : detailInfo.stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList())).list();

        SysDept condition = new SysDept();
        condition.setDeptCode("170000");
        SysDept dept = deptService.selectDeptList(condition).stream().findFirst().orElse(null);

        // 对分组遍历
        groups.keySet().forEach(l -> {
            BizOutsourcedOrderDetail bizOutsourcedOrderDetail = bizOutsourcedOrderDetails.stream().filter(e -> e.getId().equals(l)).findFirst().orElse(new BizOutsourcedOrderDetail());
            List<BizReturnReceiptDetail> itemList = groups.get(l);
            // 判断该收回明细是否已审核
            if (itemList.stream().allMatch(v -> v.getStatus().equals(0))) {
                // 未审核
                // 未审核且免检
                if (itemList.stream().allMatch(v -> v.getIsApproved().equals(1))) {
                    removeItems.addAll(bizProcessInspecions.stream().filter(e -> e.getOutsourceOrderDetailId().equals(l) && e.getIsAuto().equals(1)).collect(Collectors.toList()));
                }
            } else if (itemList.stream().allMatch(v -> v.getStatus().equals(1))) {
                // 已审核
                // 免检 且没有旧质检
                if (itemList.stream().allMatch(v -> v.getIsApproved().equals(1)) && bizProcessInspecions.stream().noneMatch(v -> v.getOutsourceOrderDetailId().equals(l))) {
                    BizReturnReceiptDetail lastProcess = itemList.stream().sorted(Comparator.comparing(BizReturnReceiptDetail::getProcessStepNumber).reversed()).findFirst().orElse(new BizReturnReceiptDetail());
                    BizProcessInspecion bizProcessInspecion = new BizProcessInspecion(lastProcess);
                    bizProcessInspecion.setProcessNames(itemList.stream().map(BizReturnReceiptDetail::getProcessAlias).collect(Collectors.joining(",")));
                    bizProcessInspecion.setOutsourceOrderId(bizOutsourcedOrderDetail.getMasterId());
                    bizProcessInspecion.setDeptId(dept != null ? dept.getDeptId() : 0L);
                    bizProcessInspecion.setProductionPlanDetailId(lastProcess.getProductionPlanDetailId());
                    bizProcessInspecion.setCarrierId(lastProcess.getCarriers().isEmpty() ? 0L : lastProcess.getCarriers().get(0).getId());
                    bizProcessInspecion.setCarrierCode(lastProcess.getCarriers().isEmpty() ? "" : lastProcess.getCarriers().get(0).getCode());
                    bizProcessInspecion.setDayworkItemId(lastProcess.getDayworkItemId());
                    bizProcessInspecion.setTenantId(getLoginUser().getTenantId());
                    bizProcessInspecion.setUserId(getLoginUser().getUserId());
                    bizProcessInspecion.setUserName(getLoginUser().getUser().getUserName());
                    bizProcessInspecion.setNickName(getLoginUser().getUser().getNickName());
                    bizProcessInspecion.setReturnReceiptDetailId(lastProcess.getId());

                    String beginCode = "WDD" + DateTime.now().toString("yyMM");
                    String previous = redisCache.hasKey(processInspectionNoKey) ? redisCache.getCacheObject(processInspectionNoKey) : "";
                    String codeValue = "";
                    if (previous.isEmpty()) {
                        List<BizProcessInspecion> processInspectionList = bizProcessInspecionService.getAllList();
                        if(!processInspectionList.isEmpty()) {
                            codeValue = processInspectionList.get(0).getOutsourcedInspectionNo();
                            int lastFourDigits = Integer.parseInt(codeValue.substring(7, 13));
                            lastFourDigits ++; // 加1
                            codeValue = codeValue.substring(0, 7) + String.format("%06d", lastFourDigits);
                            previous = codeValue;
                        }else{
                            previous = (beginCode + "000001");
                        }
                    } else {
                        codeValue = previous;
                        int lastFourDigits = Integer.parseInt(codeValue.substring(7, 13));
                        lastFourDigits ++; // 加1
                        codeValue = codeValue.substring(0, 7) + String.format("%06d", lastFourDigits);
                        previous = codeValue;
                    }
                    bizProcessInspecion.setOutsourcedInspectionNo(previous);
                    redisCache.setCacheObject(processInspectionNoKey, previous);
                    saveItems.add(bizProcessInspecion);
                }
            }
            // 判断该发出单是否需要质检
            // 判断是否已有对应的质检单
        });
        bizProcessInspecionService.removeBatchByIds(removeItems);
        bizProcessInspecionService.saveBatch(saveItems);
    }

    /**
     * 新增外协单主
     带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:add')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.INSERT)
    @Transactional
//    @PostMapping
    public AjaxResult add(@RequestBody BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException, ParseException {
        //生成单据号
        //若有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()) {
                previous = ("SHD" + formattedDate + "000001");
            } else {
                codeValue=previous;
                int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                lastFourDigits += 1; // 加1
                codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                previous=codeValue;
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizReturnReceipt.setFormCode(previous);
        }
        bizReturnReceipt.setStatus(1);
        bizReturnReceipt.setIsSubmit(1);
        //向收回单主表存
        bizReturnReceiptService.save(bizReturnReceipt);
        //将dayworkItem外协报工状态改成3,添加工时,审核数量设置成合格数
        List<Long> dayworkListIds = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getDayworkId).distinct().collect(Collectors.toList());
        //找到要修改的报工记录
        List<Long> outsourceDetailId = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getOutsourceDetailId).distinct().collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> bizOutsourcedOrderDetailProcess = bizOutsourcedOrderDetailProcessService.query().in("detail_id", outsourceDetailId).list();
        List<BizDayworkItem> dayworkItem = bizDayworkItemService.getListByDayworkIdsForOutsourced(dayworkListIds);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(simpleDateFormat.format(new Date()));
        //向收回单明细表存
        for(BizReturnReceiptDetail bizReturnReceiptDetail : bizReturnReceipt.getDetailInfo()) {
            bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
            bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
            bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
            bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
            bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
            bizReturnReceiptDetail.setIsAudit(1);
            for(BizDayworkItem item: dayworkItem) {
                for(BizOutsourcedOrderDetailProcess info: bizOutsourcedOrderDetailProcess) {
                    if (item.getDayworkId().equals(info.getDayworkId())&&item.getProcessStepNumber().equals(info.getProcessStepNumber())&& item.getLotId().equals(bizReturnReceiptDetail.getLotId())) {
                        item.setStatus("3");
                        item.setEndTime(date);
                        item.setNickName(bizReturnReceiptDetail.getSupplierName());
                        item.setQualifiedNum(bizReturnReceiptDetail.getAuditNum());
                        long timeDifference = date.getTime() - item.getStartTime().getTime();
                        item.setWorkingHours(timeDifference);
                    }
                }
            }
        }
        bizDayworkItemService.updateBatchById(dayworkItem);
        return success(bizReturnReceiptDetailService.saveBatch(bizReturnReceipt.getDetailInfo()));
    }
    /**
     * 修改外协单主
带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:edit')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.UPDATE)
    @Transactional
//    @PutMapping
    public AjaxResult edit(@RequestBody BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException, ParseException {
        bizReturnReceipt.setStatus(1);
        bizReturnReceipt.setIsSubmit(1);
        bizReturnReceiptService.updateById(bizReturnReceipt);
        //将dayworkItem外协报工状态改成3,添加工时,审核数量设置成合格数
        List<Long> dayworkListIds = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getDayworkId).collect(Collectors.toList());
        //找到要修改的报工记录
        List<Long> outsourceDetailId = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> bizOutsourcedOrderDetailProcess = bizOutsourcedOrderDetailProcessService.query().in("detail_id", outsourceDetailId.isEmpty()? Collections.singletonList(0L) : bizReturnReceipt.getDetails().stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList())).list();
        List<BizDayworkItem> dayworkItem = bizDayworkItemService.getListByDayworkIdsForOutsourced(dayworkListIds.size()>0?dayworkListIds:Collections.singletonList(0L));
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = dateFormat.parse(dateFormat.format(new Date()));
        //向收回单明细表存
        for(BizReturnReceiptDetail bizReturnReceiptDetail : bizReturnReceipt.getDetailInfo()) {
            bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
            bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
            bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
            bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
            bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
            bizReturnReceiptDetail.setIsAudit(1);
            for(BizDayworkItem item: dayworkItem) {
                    if (item.getDayworkId().equals(bizReturnReceiptDetail.getDayworkId())&&item.getProcessStepNumber().equals(bizReturnReceiptDetail.getProcessStepNumber()) && item.getLotId().equals(bizReturnReceiptDetail.getLotId())) {
                        item.setStatus("3");
                        item.setEndTime(date);
                        item.setNickName(bizReturnReceiptDetail.getSupplierName());
                        item.setQualifiedNum(bizReturnReceiptDetail.getAuditNum());
                        long timeDifference = date.getTime() - item.getStartTime().getTime();
                        item.setWorkingHours(timeDifference);
                    }
            }
        }
        bizDayworkItemService.updateBatchById(dayworkItem);
        List<BizReturnReceiptDetail> oldList = bizReturnReceiptDetailService.query().eq("master_id", bizReturnReceipt.getId()).list();
        saveOrUpdateBatch(bizReturnReceiptDetailService, bizReturnReceipt.getDetailInfo(),oldList);
        //如果收回单里面没收回明细，则主表同时删除
        if(bizReturnReceipt.getDetailInfo().size()==0) {
            bizReturnReceiptService.removeById(bizReturnReceipt.getId());
        }
        return success();
    }
    /**
     * 修改外协单主
     带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:edit')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.UPDATE)
    @Transactional
    @PutMapping
    public AjaxResult editNew(@RequestBody BizReturnReceipt bizReturnReceipt) throws NoSuchFieldException, IllegalAccessException, ParseException {
        // 判断是否有processes
        // 假设没有加个假的processes
        List<String> codes = new ArrayList<>();
        codes.add("27110");
        codes.add("28030");
        codes.add("28080");
        codes.add("27070");
        LoginUser user = getLoginUser();
        List<String> processCodes = bizReturnReceipt.getProcesses() == null ? codes : bizReturnReceipt.getProcesses();

        bizReturnReceipt.setStatus(1);
        bizReturnReceipt.setIsSubmit(1);
        bizReturnReceiptService.updateById(bizReturnReceipt);
        // 获取载具们
        String carriers = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getNewCarrier).collect(Collectors.joining(","));
        List<String> carrierCodes = Arrays.stream(carriers.split(",")).collect(Collectors.toList());
        List<BizCarrier> carrierList = bizCarrierService.query().in("code", carrierCodes.isEmpty() ? Collections.singletonList("0") : carrierCodes).list();
        //将dayworkItem外协报工状态改成3,添加工时,审核数量设置成合格数
        List<Long> dayworkListIds = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getDayworkId).collect(Collectors.toList());
        //找到要修改的报工记录
        List<Long> outsourceDetailId = bizReturnReceipt.getDetailInfo().stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList());
        List<BizOutsourcedOrderDetailProcess> bizOutsourcedOrderDetailProcess = bizOutsourcedOrderDetailProcessService.query().in("detail_id", outsourceDetailId.isEmpty()? Collections.singletonList(0L) : bizReturnReceipt.getDetails().stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList())).list();
        List<BizDayworkItem> dayworkItem = bizDayworkItemService.getListByDayworkIdsForOutsourced(dayworkListIds.size()>0?dayworkListIds:Collections.singletonList(0L));
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = dateFormat.parse(dateFormat.format(new Date()));
        List<BizProcessInspecion> processInspecionList = new ArrayList<>();
        // 获取批次信息
        List<BizLot> bizLotList = bizLotService.query().in("id", dayworkItem.isEmpty() ? Collections.singletonList(0L) : dayworkItem.stream().map(BizDayworkItem::getLotId).collect(Collectors.toList())).list();
        //向收回单明细表存
        for(BizReturnReceiptDetail bizReturnReceiptDetail : bizReturnReceipt.getDetailInfo()) {
            bizReturnReceiptDetail.setMasterId(bizReturnReceipt.getId());
            bizReturnReceiptDetail.setFormCode(bizReturnReceipt.getFormCode());
            bizReturnReceiptDetail.setSupplierId(bizReturnReceipt.getSupplierId());
            bizReturnReceiptDetail.setSupplierName(bizReturnReceipt.getSupplierName());
            bizReturnReceiptDetail.setFormDate(bizReturnReceipt.getFormDate());
            bizReturnReceiptDetail.setIsAudit(1);
            bizReturnReceiptDetail.setIsApproved(processCodes.stream().noneMatch(e -> bizReturnReceiptDetail.getProcessCode().equals(e)) ? 1 : 0);
            for(BizDayworkItem item: dayworkItem) {
                if (item.getDayworkId().equals(bizReturnReceiptDetail.getDayworkId())&&item.getProcessStepNumber().equals(bizReturnReceiptDetail.getProcessStepNumber()) && item.getLotId().equals(bizReturnReceiptDetail.getLotId())) {
                    item.setStatus("3");
                    item.setEndTime(date);
                    item.setNickName(bizReturnReceiptDetail.getSupplierName());
                    item.setQualifiedNum(bizReturnReceiptDetail.getAuditNum());
                    long timeDifference = date.getTime() - item.getStartTime().getTime();
                    item.setWorkingHours(timeDifference);
                }
                if (item.getDayworkId().equals(bizReturnReceiptDetail.getDayworkId()) && item.getProcessStepNumber().equals(bizReturnReceiptDetail.getProcessStepNumber())) {
                    bizReturnReceiptDetail.setProductionPlanDetailId(item.getProductionPlanDetailId());
                    bizReturnReceiptDetail.setDayworkItemId(item.getId());
                    bizReturnReceiptDetail.setCarriers(carrierList.stream().filter(v -> Arrays.stream(bizReturnReceiptDetail.getNewCarrier().split(",")).anyMatch(t -> v.getCode().equals(t))).collect(Collectors.toList()));
                }
            }
        }
        bizDayworkItemService.updateBatchById(dayworkItem);
        List<BizReturnReceiptDetail> oldList = bizReturnReceiptDetailService.query().eq("master_id", bizReturnReceipt.getId()).list();
        saveOrUpdateBatch(bizReturnReceiptDetailService, bizReturnReceipt.getDetailInfo(),oldList);
        //如果收回单里面没收回明细，则主表同时删除
        if(bizReturnReceipt.getDetailInfo().size()==0) {
            bizReturnReceiptService.removeById(bizReturnReceipt.getId());
        }
        addProcessInspection(bizReturnReceipt.getDetailInfo(), processCodes);
        bizProcessInspecionService.saveBatch(processInspecionList);
        return success();
    }

    /**
     * 删除外协单主
带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
    @PreAuthorize("@ss.hasPermi('business:returnReceipt:remove')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.DELETE)
    @Transactional
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids)
    {

        List<BizReturnReceiptDetail> bizReturnReceiptDetailList = bizReturnReceiptDetailService.query().in("master_id", ids).list();
        List<Long> bizReturnReceiptDetailIds = bizReturnReceiptDetailList.stream().map(BizReturnReceiptDetail::getId).collect(Collectors.toList());
        List<Long> outsourceDetailIds= bizReturnReceiptDetailList.stream().map(BizReturnReceiptDetail::getOutsourceDetailId).collect(Collectors.toList());
        //根据回收明细查询是否已经周转
        List<BizOutsourcedOrderDetail> outsourceDetailList =  bizOutsourcedOrderDetailService.query().in("id", outsourceDetailIds).ne("production_dept_id", 0).list();
        // 判断是否已结算
        List<BizOutsourceBalanceAccount> balanceAccountList = bizOutsourceBalanceAccountService.query().in("return_receipt_id", ids).list();
        List<BizProcessInspecion> inspections = bizProcessInspecionService.query().in("return_receipt_detail_id", bizReturnReceiptDetailIds).list();
        // 判断是否已质检
        if(outsourceDetailList.size() > 0){
            throw new RuntimeException("已有批次周转下序，不能删除");
        }
        if (balanceAccountList.size() > 0) {
            throw new RuntimeException("已有外协已进入结算，不能删除");
        }
        if (inspections.size() > 0) {
            throw new RuntimeException("有外协已质检，不能删除");
        }


        bizReturnReceiptService.removeBatchByIds(ids);
        return toAjax(bizReturnReceiptDetailService.removeBatchByIds(bizReturnReceiptDetailIds));
    }

    @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 success(message.get(), false);
        }
    }
}
