package com.junmp.jyzb.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junmp.junmpProcess.dto.StartProcessInstanceDTO;
import com.junmp.junmpProcess.service.IFlowInstanceService;
import com.junmp.jyzb.api.bean.dto.*;
import com.junmp.jyzb.api.bean.dto.tempDto.InventoryDetailDto;
import com.junmp.jyzb.api.bean.query.BussinessInventoryReq;
import com.junmp.jyzb.api.bean.query.InventorySumReq;
import com.junmp.jyzb.api.bean.query.QueryEquipmentTypeReq;
import com.junmp.jyzb.api.bean.req.*;
import com.junmp.jyzb.api.constant.JYZBConstant;
import com.junmp.jyzb.api.exception.enums.InventoryExceptionEnum;
import com.junmp.jyzb.cache.MsgRedisCache;
import com.junmp.jyzb.entity.*;
import com.junmp.jyzb.mapper.BussinessInventoryMapper;
import com.junmp.jyzb.mapper.InventoryMapper;
import com.junmp.jyzb.service.*;
import com.junmp.jyzb.utils.DateTimeUtil;
import com.junmp.jyzb.utils.RabbitMQSendMsg;
import com.junmp.v2.common.exception.base.ServiceException;
import com.junmp.v2.common.util.BeanPlusUtil;
import com.junmp.v2.db.api.factory.PageFactory;
import com.junmp.v2.db.api.factory.PageResultFactory;
import com.junmp.v2.db.api.page.PageResult;
import com.junmp.v2.dict.entity.SysDict;
import com.junmp.v2.dict.entity.SysDictItem;
import com.junmp.v2.dict.service.SysDictItemService;
import com.junmp.v2.dict.service.SysDictService;
import com.junmp.v2.message.api.MessageApi;
import com.junmp.v2.message.api.bean.req.MessageSendReq;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BussinessInventoryServiceImpl extends ServiceImpl<BussinessInventoryMapper, BussinessInventory>
        implements BussinessInventoryService {

    @Resource
    private IFlowInstanceService FlowInstanceService;
    @Resource
    private BussinessInventoryMapper bussinessInventoryMapper;

    @Resource
    private TaskService taskService;
    @Resource
    private InventorySummaryService inventorySummaryService;
    @Resource
    private SysDictItemService sysDictItemService;
    @Resource
    private SysDictService sysDictService;
    @Resource
    private BussinessInventoryDetailService bussinessInventoryDetailService;
    @Resource
    private BussinessInventoryChildrenDetailService bussinessInventoryChildrenDetailService;
    @Resource
    private WarehouseService warehouseService;
    @Resource
    private PubOrgService orgService;
    @Resource
    private MsgRedisCache redisCache;
    @Resource
    private MessageApi messageApi;
    @Resource
    private WarehouseInventoryService warehouseInventoryService;
    @Resource
    private LogSummaryService logSummaryService;
    @Resource
    private InventoryService inventoryService;

    @Resource
    private EquipmentTypeService equipmentTypeService;

    @Resource
    private InventoryMapper inventoryMapper;
    @Resource
    private OrderNumService orderNumService;
    @Autowired
    private RabbitMQSendMsg MQ;

    @Transactional(rollbackFor = Exception.class)
    public String AddInvOrder(UpdateInventoryReq req) {
        if (StringUtils.isNotBlank(req.getId()))
        {
            BussinessInventory BI=this.getById(req.getId());
            Warehouse warehouse= warehouseService.getById(req.getWarehouseId());
            PubOrg pubOrg=orgService.getById(req.getOrgId());
            BeanPlusUtil.copyProperties(req,BI);
            BI.setResult("ready");
            BI.setWarehouseName(warehouse.getName());
            if (StringUtils.isNotBlank(pubOrg.getDName()) )
            {
                BI.setOrgName(pubOrg.getOrgName());
            }
            else
            {
                BI.setOrgName(pubOrg.getDName());
            }
            BI.setUpdateTime(DateTimeUtil.getCurrentDateTime());
            //执行工作流
            if (req.getExamineState().equals("working"))
            {
                StartProcessInstanceDTO startProcessInstanceDTO=new StartProcessInstanceDTO();
                startProcessInstanceDTO.setProcessDefinitionId(req.getProcessDefinitionId());
                startProcessInstanceDTO.setOrderId(BI.getId());
                startProcessInstanceDTO.setTypeOrder("stocktakeOrder");
                startProcessInstanceDTO.setType("stocktakeDto");
                String ProcessInstanceId= FlowInstanceService.startProcessInstanceById(startProcessInstanceDTO);
                BI.setProcessId(ProcessInstanceId);

                String assigns= FlowInstanceService.GetNextAssign(ProcessInstanceId);//这里需要手动更新审核人信息
                BI.setCurrentAssign(assigns);
//                updateById(BI);

            }

            updateById(BI);

            String objJson= redisCache.get(BI.getProcessId());
            redisCache.remove(BI.getProcessId());
            List<MessageSendReq> msgs= JSONObject.parseArray(objJson,MessageSendReq.class);
            if (CollectionUtil.isNotEmpty(msgs)){
                msgs.forEach(msg->
                        {
                            messageApi.sendMessageNoToken(msg);
                        }

                );
            }
            return BI.getId();
        }
        else
        {
            BussinessInventory BI = new BussinessInventory();
            Warehouse warehouse= warehouseService.getById(req.getWarehouseId());
            PubOrg pubOrg=orgService.getById(req.getOrgId());
            BeanPlusUtil.copyProperties(req,BI);
            BI.setWarehouseName(warehouse.getName());
            BI.setResult("ready");
            //设置单号

            BI.setOrgName(ObjectUtil.isNull(pubOrg.getDName()) ? pubOrg.getOrgName():pubOrg.getDName());

            BI.setYear(LocalDate.now().getYear());
            BI.setMonth(Integer.valueOf(LocalDate.now().getMonthValue()));

            OrderNum orderNum = setOrderCode("bussinessInventory",req.getOrgId());
            long time = new Date().getTime() % 10000;
            String codeValue=String.format("%04d",orderNum.getNum());
            BI.setOrderNum(orderNum.getBussinessType()+String.format("%04d",time) + orderNum.getYear()+
                    String.format("%02d", LocalDateTime.now().getMonth().getValue())+
                    String.format("%02d",LocalDateTime.now().getDayOfMonth())+codeValue);

            BI.setCreateTime(DateTimeUtil.getCurrentDateTime());
            BI.setUpdateTime(DateTimeUtil.getCurrentDateTime());
            BI.setInventoryState("waitting");
            //执行工作流
            if (req.getExamineState().equals("working"))
            {
                StartProcessInstanceDTO startProcessInstanceDTO=new StartProcessInstanceDTO();
                startProcessInstanceDTO.setProcessDefinitionId(req.getProcessDefinitionId());
                startProcessInstanceDTO.setOrderId(BI.getId());
                startProcessInstanceDTO.setTypeOrder("stocktakeOrder");
//            startProcessInstanceDTO.setUserId(req.getUserId());
                String processInstanceId= FlowInstanceService.startProcessInstanceById(startProcessInstanceDTO);

                //list返回数据
                List<String> list=new ArrayList<>();
                //当前审核是否跳过
                if (processInstanceId!=null && processInstanceId.substring(0,4).equals("skip") ){
                    String substring = processInstanceId.substring(4);

                    BI.setProcessId(substring);
                    if (ObjectUtil.isNotNull(req.getId()) && !req.getId().trim().isEmpty()) {
                        updateById(BI);
                    } else {
                        //保存
                        this.save(BI);
                    }
                    Task currentTask = taskService.createTaskQuery().processInstanceId(substring).singleResult();
                    // 直接完成当前任务
                    taskService.complete(currentTask.getId());
                }else {
                    BI.setProcessId(processInstanceId);
                    if (StringUtils.isNotBlank(req.getId())) {
                        updateById(BI);
                    } else {
                        //保存
                        this.save(BI);
                    }
                }
                list.add(BI.getId());


            }else {

                this.save(BI);
            }
            return BI.getId();}

    }


    @Transactional(rollbackFor = Exception.class)
    public ViewCountDto GetInfoByEpcs(UploadInventoryReq req) {
        List<String> UpdateInventorys;

        if (req.getEpcList()!=null&&req.getEpcList().contains(",")) {
            UpdateInventorys = Arrays.asList(req.getEpcList().split(","));
        } else {
            UpdateInventorys = new ArrayList<>(Collections.singletonList(req.getEpcList()));
        }
        ViewCountDto viewEd=new ViewCountDto();
        viewEd.setEqList(inventoryMapper.GetViewCountByepcs(UpdateInventorys));
        List<String> existEpc=inventoryMapper.checkEPCList(UpdateInventorys);
        // 找出在UpdateInventorys中有但existEpc中没有的数据，并进行拼接
        List<String> notInExistEpc = UpdateInventorys.stream()
                .filter(epc -> !existEpc.contains(epc))
                .collect(Collectors.toList());
        if (notInExistEpc.size()>0)
        {
            String result = String.join(", ", notInExistEpc);
            viewEd.setErrorEPC(result);
        }

        return viewEd;
    }

    @Transactional(rollbackFor = Exception.class)
    public String DeleteOrder(UpdateInventoryReq req) {
        if (StringUtils.isNotBlank(req.getId()))
        {
            BussinessInventory BI=this.getById(req.getId());
            if (BI.getInventoryState().equals("waitting")&&BI.getExamineState().equals("none"))
            {
                this.removeById(BI);
            }
            else
            {
                throw new ServiceException(InventoryExceptionEnum.RUNNINGORDER_EXIST);
            }

            return req.getId();

    }
        return req.getId();
    }

    @Override
    public BussinessInventoryDto Check(BussinessInventoryReq req) {
        String Id=req.getOrderId();
        if (StringUtils.isNotBlank(Id))//如果传了订单号，则全部通过订单号查询
        {
           BussinessInventory inventory= this.getById(Id);
            String type=inventory.getInventoryType().toString();
            String warehouseId=inventory.getWarehouseId();
            InventorySumReq sumreq=new InventorySumReq();
            sumreq.setLocationType("0");
            sumreq.setLocationId(warehouseId);
            BussinessInventoryDto BIDto=new BussinessInventoryDto();
            String rules="盘点规则-";
                if (type.equals("1"))//按装备类型盘点
                {
                    List<String> typeIds = Arrays.asList(inventory.getRules().split(","));
                    sumreq.setTypeIds(typeIds);

                    QueryEquipmentTypeReq typeReq=new QueryEquipmentTypeReq();
                    typeReq.setTypeIds(inventory.getRules());
                    String types= equipmentTypeService.GetEquipmentByIds(typeReq);
                    rules=rules+"类别盘点:"+types;
                } else if (type.equals("2"))//按装备号型盘点
                {
                    QueryEquipmentTypeReq typeReq=new QueryEquipmentTypeReq();
                    List<String> sizeIds = Arrays.asList(inventory.getRules().split(","));
                    sumreq.setSizeIds(sizeIds);
                    typeReq.setSizeIds(inventory.getRules());
                    String sizes= equipmentTypeService.GetEquipmentBySizeIds(typeReq);

                    rules=rules+"类别及号型盘点:"+sizes;
                }
                else
                {
                    rules=rules+"整库盘点";
                }
            BIDto.setRules(rules);
            List<EquipmentListDto> eqList = new ArrayList<>();
            Integer totalNumber = 0;

// 使用Map来追踪已经处理过的数据
            Map<String, EquipmentListDto> processedData = new HashMap<>();

            List<InventorySummary> SumResult = inventorySummaryService.getEquipmentInfoList(sumreq);
            for (InventorySummary summary : SumResult) {
                String key = summary.getSizeId() + "-" + summary.getTypeId();

                if (processedData.containsKey(key)) {
                    // 如果已经存在相同的key，更新已有的数据
                    EquipmentListDto existingDto = processedData.get(key);
                    existingDto.setPlanNum(String.valueOf(Integer.parseInt(existingDto.getPlanNum()) + summary.getStockNumber()));
                    totalNumber += summary.getStockNumber();
                } else {
                    // 如果是新的key，创建新的EquipmentListDto并添加到eqList中
                    EquipmentListDto eq = new EquipmentListDto();
                    BeanPlusUtil.copyProperties(summary, eq);
                    eq.setPlanNum(String.valueOf(summary.getStockNumber()));
                    totalNumber += summary.getStockNumber();
                    eqList.add(eq);

                    // 将新的数据放入Map中
                    processedData.put(key, eq);
                }
            }
            BIDto.setTotalNum(String.valueOf(totalNumber));
            BIDto.setEquipmentList(eqList);
            return  BIDto;
        }
        String type=req.getType();
        String warehouseId=req.getWarehouseId();
        InventorySumReq sumreq=new InventorySumReq();
        sumreq.setLocationType("0");
        sumreq.setLocationId(warehouseId);

        BussinessInventoryDto BIDto=new BussinessInventoryDto();
        if (ObjectUtil.isEmpty(type) || ObjectUtil.isNull(type)) {
        }
        else {
            if (type.equals("1"))//按装备类型盘点
            {
                List<String> typeIds = Arrays.asList(req.getTypeList().split(","));
                sumreq.setTypeIds(typeIds);
            } else if (type.equals("2"))//按装备号型盘点
            {
                List<String> sizeIds = Arrays.asList(req.getTypeList().split(","));
                sumreq.setSizeIds(sizeIds);
            }
        }
        List<EquipmentListDto> eqList = new ArrayList<>();
        Integer totalNumber = 0;

// 使用Map来追踪已经处理过的数据
        Map<String, EquipmentListDto> processedData = new HashMap<>();

        List<InventorySummary> SumResult = inventorySummaryService.getEquipmentInfoList(sumreq);

        for (InventorySummary summary : SumResult) {
            String key = summary.getSizeId() + "-" + summary.getTypeId();

            if (processedData.containsKey(key)) {
                // 如果已经存在相同的key，更新已有的数据
                EquipmentListDto existingDto = processedData.get(key);
                existingDto.setPlanNum(String.valueOf(Integer.parseInt(existingDto.getPlanNum()) + summary.getStockNumber()));
                totalNumber += summary.getStockNumber();
            } else {
                // 如果是新的key，创建新的EquipmentListDto并添加到eqList中
                EquipmentListDto eq = new EquipmentListDto();
                BeanPlusUtil.copyProperties(summary, eq);
                eq.setPlanNum(String.valueOf(summary.getStockNumber()));
                totalNumber += summary.getStockNumber();
                eqList.add(eq);

                // 将新的数据放入Map中
                processedData.put(key, eq);
            }
        }
            BIDto.setTotalNum(String.valueOf(totalNumber));
            BIDto.setEquipmentList(eqList);
            return  BIDto;

    }

    //开始盘点
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean Start(UploadInventoryReq req) {


        String orderId=req.getOrderId();
        BussinessInventory bi= this.getById(orderId);

        BussinessInventory biexist=this.getOne(new LambdaQueryWrapper<BussinessInventory>()
                .eq(BussinessInventory::getWarehouseId, bi.getWarehouseId())
                .eq(BussinessInventory::getInventoryState,"running"));
        if (biexist!=null)
        {
            throw new ServiceException(InventoryExceptionEnum.RUNNINGORDER_EXIST);
        }

       Warehouse warehouse= warehouseService.getById(bi.getWarehouseId());
        warehouse.setIsLocked(1);
        if (bi.getInventoryState().equals("running"))
        {
            throw new ServiceException(InventoryExceptionEnum.ORDER_HAS_START);
        }
        List<BussinessDetail> BDList=new ArrayList<>();
        if (CollectionUtil.isNotEmpty(req.getEquipmentList())){
            for (EquipmentListDto bd:
                    req.getEquipmentList()) {
                BussinessDetail bdInsert=new BussinessDetail();
                bdInsert.setInventoryId(Long.valueOf(req.getOrderId()));
                BeanPlusUtil.copyProperties(bd,bdInsert);
                bdInsert.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                BDList.add(bdInsert);
            }
            bussinessInventoryDetailService.saveBatch(BDList);
        }
        warehouseService.updateById(warehouse);
        String msg="盘库单:【"+bi.getOrderNum()+"】正在进行盘点，仓库:"+bi.getWarehouseName()+",该仓库已锁定，请勿执行记账操作";
        sendAsyncReminder(bi,msg,"systemInvMsg");
        if (bi!=null)
        {
            bi.setInventoryState("running");
            this.updateById(bi);
        }
        else
        {
            throw new ServiceException(InventoryExceptionEnum.ORDER_NOT_EXIST);
        }
        return true;
    }


    @Override
    public List<BussinessDetailChildDto> GetDetailChild(DetailInvReq req) {
        List<BussinessInventoryChildrenDetail> detailChild= bussinessInventoryChildrenDetailService.list(
                new LambdaQueryWrapper<BussinessInventoryChildrenDetail>().eq(BussinessInventoryChildrenDetail::getInvDetailId, req.getDetailId())
        );
        List<BussinessDetailChildDto> eqDtoList=new ArrayList<>();

        for (BussinessInventoryChildrenDetail child : detailChild) {
            BussinessDetailChildDto eqDto = new BussinessDetailChildDto();
            BeanPlusUtil.copyProperties(child, eqDto);

            eqDtoList.add(eqDto);
        }

        return eqDtoList;
    }
    @Override
    public BussinessInventoryDto GetDetailById(BussinessInventoryReq req) {
        BussinessInventory inventory=new BussinessInventory();
        if (ObjectUtil.isNotEmpty(req.getOrderId())){

            inventory= this.getById(req.getOrderId());
        } else if (ObjectUtil.isNotEmpty(req.getProcessId())) {
            inventory=getOne(new LambdaQueryWrapper<BussinessInventory>().eq(BussinessInventory::getProcessId,req.getProcessId()));
        }
        String rules="盘点规则-";

        if (inventory.getInventoryType().equals(1))//按装备类型盘点
        {
            QueryEquipmentTypeReq typeReq=new QueryEquipmentTypeReq();
            typeReq.setTypeIds(inventory.getRules());
            String types= equipmentTypeService.GetEquipmentByIds(typeReq);
            rules=rules+"类别盘点:"+types;
        } else if (inventory.getInventoryType().equals(2))//按装备号型盘点
        {
            QueryEquipmentTypeReq typeReq=new QueryEquipmentTypeReq();
            typeReq.setSizeIds(inventory.getRules());
            String sizes= equipmentTypeService.GetEquipmentBySizeIds(typeReq);
            rules=rules+"类别及号型盘点:"+sizes;
        }
        else
        {
            rules=rules+"整库盘点";
        }

        List<InventoryDetailDto> detailsMain= bussinessInventoryMapper.GetBussinessInventoryMap(req.getOrderId());
        List<BussinessDetail> detailsChildren = bussinessInventoryDetailService.list(
                    new LambdaQueryWrapper<BussinessDetail>().eq(BussinessDetail::getInventoryId, req.getOrderId())
            );

    List<EquipmentListDto> eqDtoList=new ArrayList<>();
        BussinessInventoryDto BIDTO=new BussinessInventoryDto();
        BIDTO.setRulesText(rules);
        BeanPlusUtil.copyProperties(inventory,BIDTO);
        for (InventoryDetailDto detail : detailsMain) {
            EquipmentListDto eqDto = new EquipmentListDto();
            BeanPlusUtil.copyProperties(detail, eqDto);
            List<BussinessDetail> matchingDetails = new ArrayList<>();
            // 找出所有group_id匹配的detailChild并加入到matchingDetails列表中
            List<BussinessDetail> filteredDetails = detailsChildren.stream()
                    .filter(detailChild -> detailChild.getGroupId() != null && detailChild.getGroupId().equals(detail.getGroupId()))
                    .collect(Collectors.toList()); // 收集所有匹配的项

            // 将所有筛选出的子项添加到matchingDetails
            matchingDetails.addAll(filteredDetails);
            List<EquipmentListDto.PriceInfo> priceInfos=new ArrayList<>();
            for (BussinessDetail filterDetail :matchingDetails) {
                EquipmentListDto.PriceInfo priceInfo=new EquipmentListDto.PriceInfo();
                priceInfo.setPrice(filterDetail.getPrice());
                priceInfo.setId(String.valueOf(filterDetail.getId()));
                priceInfo.setHasCount(String.valueOf(filterDetail.getHasCount()));
                priceInfo.setAccountNumber(Integer.valueOf(filterDetail.getAccountNum()));
                priceInfo.setStockPrice(filterDetail.getStockPrice());
                priceInfo.setStockNum(String.valueOf(filterDetail.getStockNumber()));
                priceInfo.setNum(String.valueOf(filterDetail.getFixNumber()));
                priceInfos.add(priceInfo);
            }
            eqDto.setPriceInfo(priceInfos);
//            priceInfo.add(matchingDetails.forEach(p->p.);)


//            eqDto.setAccountNumber(detail.getAccountNum());

            eqDtoList.add(eqDto);
        }
        BIDTO.setState(inventory.getResult());
        BIDTO.setEquipmentList(eqDtoList);
        return BIDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean UploadStock(UploadInventoryReq req) {
        //更新之前先把库存表的epc备份
       BussinessInventory BI=  this.getById(req.getOrderId());
       if (BI==null)
       {
           throw new ServiceException(InventoryExceptionEnum.ORDER_NOT_EXIST);
       }
        if (BI.getInventoryState().equals("close"))
        {
            throw new ServiceException(InventoryExceptionEnum.ORDER_CLOSED);
        }
        List<BussinessDetail> ChildrenList = bussinessInventoryDetailService.list(
                new LambdaQueryWrapper<BussinessDetail>().eq(BussinessDetail::getInventoryId, req.getOrderId())
        );
        for (BussinessDetail detail : ChildrenList) {
            List<BussinessInventoryChildrenDetail> ChildrenDetail = bussinessInventoryChildrenDetailService.list(
                    new LambdaQueryWrapper<BussinessInventoryChildrenDetail>().eq(BussinessInventoryChildrenDetail::getInvDetailId, detail.getId())
            );
            if (ChildrenDetail.size()>0)//子单据有数据就先清除
            {
                bussinessInventoryChildrenDetailService.removeBatchByIds(ChildrenDetail);
            }
        }
        if (ChildrenList.size()>0)
        {
            bussinessInventoryDetailService.removeBatchByIds(ChildrenList);
        }
        List<BussinessInventoryChildrenDetail> ChildrenInfo=new ArrayList<>();
        //将上报的数据传入数据库存储
        BeanPlusUtil.copyProperties(req,BI);
        List<BussinessDetail> Bussinessdetails=new ArrayList<>();
        for (EquipmentListDto detail : req.getEquipmentList()) {
            String detailUUID=UUID.randomUUID().toString();
            for (EquipmentListDto.PriceInfo priceEq :detail.getPriceInfo())
            {
                BussinessDetail eqDto = new BussinessDetail();
                BeanPlusUtil.copyProperties(detail, eqDto);
                eqDto.setGroupId(detailUUID);
                eqDto.setNum(Integer.valueOf(detail.getNum()));
                eqDto.setFixNumber(Integer.valueOf(priceEq.getNum()));
                eqDto.setFixPrice(priceEq.getStockPrice());
                eqDto.setPrice(priceEq.getPrice());
//                eqDto.setStockPrice(priceEq.getStockPrice());
                eqDto.setAccountNum(String.valueOf(priceEq.getAccountNumber()));
                eqDto.setInventoryId(Long.valueOf(req.getOrderId()));
                eqDto.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                eqDto.setCreateTime(DateTimeUtil.getCurrentDateTime());
                if (String.valueOf(priceEq.getAccountNumber()).equals("0"))
                {
                    eqDto.setHasCount(1);
                }
                else
                {
                    eqDto.setHasCount(0);
                }
                Bussinessdetails.add(eqDto);

            }
        }
        BI.setEpcUpdate(req.getEpcList());
        BI.setResult(req.getState());
        BI.setInventoryState("finished");
        this.updateById(BI);
        bussinessInventoryDetailService.saveBatch(Bussinessdetails);


        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean UpdateDetail(UpdateDetailReq req) {


        BussinessDetail bd= bussinessInventoryDetailService.getById(req.getDetailId());
        if (bd==null)
        {
            throw new ServiceException(InventoryExceptionEnum.ORDER_Child_NOT_EXIST);
        }
        List<BussinessInventoryChildrenDetail> ChildrenDetail = bussinessInventoryChildrenDetailService.list(
                new LambdaQueryWrapper<BussinessInventoryChildrenDetail>().eq(BussinessInventoryChildrenDetail::getInvDetailId, req.getDetailId())
        );
        if (ChildrenDetail.size()>0)//子单据有数据就先清除
        {
            bussinessInventoryChildrenDetailService.removeBatchByIds(ChildrenDetail);
        }
        List<BussinessInventoryChildrenDetail> AddChildrenDetail=new ArrayList<>();

        for (UpdateDetailReq.eqList eqInfo : req.getEqList()) {
            BussinessInventoryChildrenDetail Bcd=new BussinessInventoryChildrenDetail();
            BeanPlusUtil.copyProperties(eqInfo,Bcd);
            Bcd.setInvDetailId(req.getDetailId());
            Bcd.setPrice(bd.getPrice());
            Integer num= Integer.valueOf(bd.getAccountNum());
            // 计算总价并设置
            BigDecimal totalPrice = bd.getPrice().multiply(BigDecimal.valueOf(num));
            Bcd.setTotalPrice(totalPrice);
            Bcd.setUpdateTime(DateTimeUtil.getCurrentDateTime());
            Bcd.setCreateTime(DateTimeUtil.getCurrentDateTime());
            AddChildrenDetail.add(Bcd);
        }
        bd.setHasCount(1);
        bussinessInventoryDetailService.updateById(bd);
        return bussinessInventoryChildrenDetailService.saveBatch(AddChildrenDetail);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean UseOrFinished(UploadInventoryReq req) {


        BussinessInventory BI=  this.getById(req.getOrderId());
        if (BI.getInventoryState().equals("close"))
        {
            throw new ServiceException(InventoryExceptionEnum.ORDER_CLOSED);
        }
        PubOrg org= orgService.getById(BI.getOrgId());
        if(req.getState().equals("0"))//确认结果
        {
            Map<String, Object> params = new HashMap<>();
//        List<WarehouseInventory> DeleteList;
        List<WarehouseInventory> SaveEpcList =new ArrayList<>();
        List<BussinessDetail> bussinessDetail = bussinessInventoryDetailService.list(
                new LambdaQueryWrapper<BussinessDetail>().eq(BussinessDetail::getInventoryId, req.getOrderId())
        );
            long countZeroOrNull = bussinessDetail.stream()
                    .filter(p -> p.getHasCount() == null || p.getHasCount() == 0)
                    .count();
            if (countZeroOrNull>0)
            {
                throw new ServiceException(InventoryExceptionEnum.ACCOUNT_ERROR);
            }
        InventorySumReq sumreq=new InventorySumReq();
        sumreq.setLocationType("0");
        sumreq.setLocationId(BI.getWarehouseId());
//            logSummaryService.processInventoryRecords()
        if (BI.getInventoryType().equals(1))//按装备类型盘点
        {
            List<String> typeIds = Arrays.asList(BI.getRules().split(","));
            sumreq.setTypeIds(typeIds);
            params.put("typeIds", typeIds); //
            params.put("sizeIds", Collections.emptyList()); // 添加一个空的列表
        } else if (BI.getInventoryType().equals(2))//按装备号型盘点
        {
            List<String> sizeIds = Arrays.asList(BI.getRules().split(","));
            sumreq.setSizeIds(sizeIds);
            params.put("sizeIds", sizeIds); //
            params.put("typeIds", Collections.emptyList()); // 添加一个空的列表
        }
        List<InventorySummary> SumResult = inventorySummaryService.getEquipmentInfoList(sumreq);
            List<InventorySummary> InsertSumResult=new ArrayList<>();
        if (SumResult.size()>0)//库存表中有对应数据，进行更新
        {
            for (InventorySummary summary : SumResult) {
                for (BussinessDetail bussiness : bussinessDetail) {
                    if (summary.getTypeId().equals(bussiness.getTypeId())&&summary.getUnitPrice().equals(bussiness.getPrice())
                        &&summary.getLocationId().equals(BI.getWarehouseId())&& summary.getSizeId().equals(bussiness.getSizeId())) {
                        summary.setStockNumber(bussiness.getFixNumber());
                        summary.setOutboundNumber(0);
                        summary.setNumber(bussiness.getFixNumber());
                        if (bussiness.getState().equals("1"))//盈余状态需要增加金额和数量
                        {
                            summary.setPrice( bussiness.getFixPrice());
                        }
                        else if (bussiness.getState().equals("2"))//亏损状态需要减少金额和数量
                        {
                            summary.setPrice( bussiness.getFixPrice());
                        }


                    }
                }


            }
        }
        else
        {
            for (BussinessDetail bdList :bussinessDetail) {
                InventorySummary InsertSum=inventorySummaryService.createInventorySummary(BI.getOrgId(), BI.getOrgName(),
                        org.getOrgCode(),bdList.getTypeId(),bdList.getTypeName(),bdList.getSizeId(),bdList.getSizeName(),
                        BI.getWarehouseId(), BI.getWarehouseName(),bdList.getFixNumber(),0,
                        bdList.getStockPrice(),0,0,0,0,0,0,0,"0" );

                InsertSumResult.add(InsertSum);
            }
        }


//            LambdaQueryWrapper<WarehouseInventory> queryWrapper = new LambdaQueryWrapper<>();
            params.put("warehouseId", BI.getWarehouseId()); // 添加一个空的列表
            // 从Map中获取sizeIds，假设它们存储为List类型
            List<String> sizeIds = (List<String>) params.get("sizeIds");

            List<String> typeIds = (List<String>) params.get("typeIds");
            // 检查sizeIds是否不为空且不是空列表
            if (sizeIds != null && !sizeIds.isEmpty()) {
//                queryWrapper.in(WarehouseInventory::getSizeId, sizeIds);
            }
            // 检查sizeIds是否不为空且不是空列表
            if (typeIds != null && !typeIds.isEmpty()) {
//                queryWrapper.in(WarehouseInventory::getTypeId, typeIds);
            }
//            // 添加查询条件，仅查询warehouseId符合的记录
//            queryWrapper.eq(WarehouseInventory::getLocationId, BI.getWarehouseId());
//            DeleteList = warehouseInventoryService.list(queryWrapper);
            List<InvSummaryDto> invDelete= inventoryMapper.selectEpcsByWarehouse(BI.getWarehouseId(),typeIds,sizeIds);
            List<String> removeIds = invDelete.stream() // 创建流
                    .map(InvSummaryDto::getId) // 提取每个InvSummaryDto对象的id
                    .collect(Collectors.toList()); // 收集到列表中



            List<WarehouseInvDto> DeleteFakeEpc = inventoryMapper.GetViewWarehouseInv(BI.getWarehouseId(), typeIds, sizeIds);
            List<Inventory> addInvList=new ArrayList<>();
            List<WarehouseInventory> addWareInvList=new ArrayList<>();
            List<InventoryMapDto> InvFakeList= inventoryMapper.GetViewInventoryMap(BI.getWarehouseId());

            List<BussinessInventoryChildrenDetail> updateInvChilred=new ArrayList<>();
            for (InventoryMapDto detail : InvFakeList) {
                BussinessInventoryChildrenDetail ChildrenDetail = bussinessInventoryChildrenDetailService.getById(detail.getChildrenId());
                updateInvChilred.add(ChildrenDetail);
            }
            if (updateInvChilred.size()>0)
            {
                updateInvChilred.forEach(p->p.setIsUse(1));
                updateInvChilred.forEach(p->p.setUpdateTime(DateTimeUtil.getCurrentDateTime()));
                bussinessInventoryChildrenDetailService.updateBatchById(updateInvChilred);
            }

            for (InventoryMapDto invFake:InvFakeList) {
                Random random = new Random();
                //先插入仓库实体表
                for (int i = 0; i < Integer.valueOf(invFake.getNum()); i++) {
                    String epc="000000"+DateTimeUtil.getCurrentDateTime().getTime()+(random.nextInt(999999 - 100000 + 1) + 100000);
                    Inventory inventory = new Inventory();
                    inventory.setEpc(epc);
                    inventory.setEpcType(1);
                    inventory.setPrice(invFake.getPrice());
                    inventory.setSizeId(invFake.getSizeId());
                    inventory.setTypeId(invFake.getTypeId());
                    inventory.setPrice(invFake.getPrice());
                    inventory.setProperty(0);
                    inventory.setState("normal");
                    inventory.setBussinessState("normal");
                    inventory.setCreateTime(DateTimeUtil.getCurrentDateTime());
                    inventory.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                    inventory.setProductionDate(invFake.getProductionDate());
                    inventory.setWarrantyPeriod(invFake.getWarrantyPeriod());
                    inventory.setMaintenancePeriod(invFake.getMaintenancePeriod());
                    inventory.setTypeName(invFake.getTypeName());
                    inventory.setSizeName(invFake.getSizeName());
                    inventory.setBussinessType("normal");
                    inventory.setLocationState("in");
                    addInvList.add(inventory);
                    WarehouseInventory warehouseInventory = new WarehouseInventory();
                    warehouseInventory.setOrgId(invFake.getOrgId());
                    warehouseInventory.setEpc(epc);
                    warehouseInventory.setLocationId(invFake.getWarehouseId());
                    warehouseInventory.setTypeId(invFake.getTypeId());
                    warehouseInventory.setSizeId(invFake.getSizeId());
                    warehouseInventory.setLocationType("0");
                    warehouseInventory.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                    warehouseInventory.setLocationState("in");
                    warehouseInventory.setCreateTime(DateTimeUtil.getCurrentDateTime());
                    warehouseInventory.setOrgName(invFake.getOrgName());
                    warehouseInventory.setEpcType(1);
                    warehouseInventory.setTypeName(invFake.getTypeName());
                    warehouseInventory.setSizeName(invFake.getSizeName());
                    warehouseInventory.setLocationName(invFake.getWarehouseName());
                    addWareInvList.add(warehouseInventory);
                }
                //再插入库存位置关联表
            }
            List<String> epcList = DeleteFakeEpc.stream()
                    .map(WarehouseInvDto::getEpc) // 假设 getEpc 是获取 epc 属性的方法
                    .collect(Collectors.toList());
            if (epcList.size()>0)
            {
                inventoryMapper.deleteByEpcs(epcList);//删除库存内所有epc
            }

            String epcUpdate = BI.getEpcUpdate();
            List<String> UpdateInventorys;

            if (epcUpdate!=null&&epcUpdate.contains(",")) {
                UpdateInventorys = Arrays.asList(epcUpdate.split(","));
            } else {
                UpdateInventorys = new ArrayList<>(Collections.singletonList(epcUpdate));
            }
            //需要对Summary表得数据进行更新
          List<InvSummaryDto> Summary=inventoryMapper.selectWarehouseByEpcs(UpdateInventorys, String.valueOf(BI.getOrgId()),String.valueOf(BI.getWarehouseId()));//删除同组织机构下EPC所在

            List<InventorySummary> UpdateSummary=new ArrayList<>();
            List<InventorySummary> DeleteSummary=new ArrayList<>();
            for (InvSummaryDto Isum:Summary) {
                InventorySumReq summaryreq=new InventorySumReq();
                summaryreq.setLocationId(Isum.getLocationId());
                summaryreq.setUnitPrice(String.valueOf(Isum.getPrice()));
                summaryreq.setTypeId(Isum.getTypeId());
                summaryreq.setSizeId(Isum.getSizeId());
                InventorySummary InvSum=  inventorySummaryService.getOne(summaryreq);
                if (InvSum!=null)//同组织原有仓库需要减少数量和价格
                {
                    Integer currentNumber=InvSum.getNumber()-Isum.getCount();
                    BigDecimal count = new BigDecimal(Isum.getCount());
                    BigDecimal price = Isum.getPrice();
                    BigDecimal result = count.multiply(price);
                    BigDecimal currentPrice=InvSum.getPrice().subtract(result);//当前价格
                    InvSum.setPrice(currentPrice.max(BigDecimal.ZERO));
                    InvSum.setNumber(Math.max(currentNumber, 0));
                    InvSum.setStockNumber(Math.max(currentNumber, 0));
                    InvSum.setStockNumberPrice(currentPrice.max(BigDecimal.ZERO));
                    InvSum.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                    if (InvSum.getStockNumber()==0&&InvSum.getNumber()==0&&InvSum.getFixNumber()==0&&InvSum.getBrokenNumber()==0&&InvSum.getDestructionNumber()==0&&InvSum.getOutboundNumber()==0)
                    {
                        DeleteSummary.add(InvSum);
                    }
                    else
                    {
                        UpdateSummary.add(InvSum);
                    }
                    //这里还要记上出入库的日志，用来记录原有物资减少的变化


                }

//                //同组织机构当前仓库需要增加价格和数量
//                InventorySumReq summaryNowReq=new InventorySumReq();
//                summaryNowReq.setLocationId(BI.getWarehouseId());
//                summaryNowReq.setUnitPrice(String.valueOf(Isum.getPrice()));
//                summaryNowReq.setTypeId(Isum.getTypeId());
//                summaryNowReq.setSizeId(Isum.getSizeId());
            }
          List<ViewEquipmentDto> viewEd=  inventoryMapper.GetViewEquipment(UpdateInventorys);
            for (ViewEquipmentDto inv:viewEd
                 ) {
                WarehouseInventory Wi=new WarehouseInventory();
                Wi.setEpc(inv.getEpc());
                Wi.setOrgId(BI.getOrgId());
                Wi.setLocationId(BI.getWarehouseId());
                Wi.setTypeId(inv.getTypeId());
                Wi.setSizeId(inv.getSizeId());
                Wi.setLocationType("0");
                Wi.setLocationState("in");
                Wi.setOrgName(BI.getOrgName());
                Wi.setEpcType(0);
                Wi.setTypeName(inv.getTypeName());
                Wi.setSizeName(inv.getSizeName());
                Wi.setLocationName(BI.getWarehouseName());
                Wi.setLocationId(BI.getWarehouseId());
                Wi.setLocationType("0");
                Wi.setCreateTime(DateTimeUtil.getCurrentDateTime());
                Wi.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                SaveEpcList.add(Wi);
            }
            BI.setInventoryState("close");
            BI.setUpdateTime(DateTimeUtil.getCurrentDateTime());
            //删除同组织机构下该EPC其他仓库的位置信息
            inventoryMapper.DeleteEpcsWithoutWarehouse(UpdateInventorys, String.valueOf(BI.getOrgId()),String.valueOf(BI.getWarehouseId()));
//            if (DeleteList.size()>0)//删除库内全部的EPC信息
//            {
//                warehouseInventoryService.removeBatchByIds(DeleteList);
//            }
            if (removeIds.size()>0)//删除库内全部的EPC信息
            {
                warehouseInventoryService.removeByIds(removeIds);
            }

            if (DeleteSummary.size()>0)
            {
                inventorySummaryService.removeBatchByIds(DeleteSummary);
            }
            if (UpdateSummary.size()>0)//同组织机构的其他不同仓库的物资
            {
                inventorySummaryService.updateBatchById(UpdateSummary);
            }
            if (SumResult.size()>0)//当前组织机构盘点后的物资汇总信息
            {
                inventorySummaryService.updateBatchById(SumResult);
            }
            if (SaveEpcList.size()>0)//将新的库内EPC存入新仓库
            {
                warehouseInventoryService.saveBatch(SaveEpcList);
            }


            if (InsertSumResult.size()>0)//当前仓库下没有该物资，需要新增该物资的信息
            {
                inventorySummaryService.saveBatch(InsertSumResult);
            }
            //入库添加虚拟装备
            if (CollectionUtil.isNotEmpty(addInvList)){
                inventoryService.saveBatch(addInvList);
            }
            //入库添加虚拟装备
            if (CollectionUtil.isNotEmpty(addWareInvList)){
                warehouseInventoryService.saveBatch(addWareInvList);
            }
            Warehouse warehouse= warehouseService.getById(BI.getWarehouseId());
            warehouse.setIsLocked(0);
            warehouseService.updateById(warehouse);
            this.updateById(BI);
            MQ.SendMsg("orderExchange", BI.getOrgId().toString(),"BussinessInventoryFinish",-1,
                    "BussinessInventoryFinish",null,null,new ArrayList<>(),BI.getId(),"finished");
        }
        else//废除单据   req.getState().equals(1)
        {
            Warehouse warehouse= warehouseService.getById(BI.getWarehouseId());
            warehouse.setIsLocked(0);
            warehouseService.updateById(warehouse);
            BI.setInventoryState("cancel");
            BI.setUpdateTime(DateTimeUtil.getCurrentDateTime());
            this.updateById(BI);
            MQ.SendMsg("orderExchange", BI.getOrgId().toString(),"BussinessInventoryFinish",-1,
                    "BussinessInventoryFinish",null,null,new ArrayList<>(),BI.getId(),"cancel");
        }

        String Msg="盘库单:【"+BI.getOrderNum()+"】已结束，仓库:"+BI.getWarehouseName()+",该仓库已解锁";
        sendAsyncReminder(BI,Msg,"Inventory/pass");//异步推送消息

        return true;
    }
    @Async
    public void sendAsyncReminder(BussinessInventory BI,String Msg,String type) {
        //盘点进行中，需要为所有人员推送信息
        MessageSendReq sendReq = new MessageSendReq();
        List<Long> uniqueOrgIDsList = new ArrayList<>();
        uniqueOrgIDsList.add(BI.getOrgId());
        //查询组织机构下面的所有仓管员的useId
        List<InvExpireReq> userIdsList=inventoryMapper.selectUserListByOrgs(uniqueOrgIDsList, JYZBConstant.GL_ROLR_ID.toString());
        String userIds = userIdsList.stream()
                .map(InvExpireReq::getUserId)  // 获取所有的userId
                .collect(Collectors.joining(","));
        sendReq.setReceiveUserIds(userIds);
        sendReq.setMsgTitle("盘点提醒");
        sendReq.setBizType(type);
        sendReq.setBizId(Long.valueOf(BI.getId()));
        sendReq.setSendUserId(String.valueOf(1000));
        sendReq.setMsgContent(Msg);
        sendReq.setPriority("0");
        sendReq.setSendTime(DateTime.now());
        messageApi.sendMessageNoToken(sendReq);
    }
    @Override
    public PageResult<BussinessInventory> GetPage(BussinessInventoryReq req) {
        //排序字段处理，将驼峰改成和数据库同步的字段名(如果传其他不是数据库字段参数或者排序规则不是deac或者asc可能会出现错误)
        if (ObjectUtil.isNotNull(req.getColumn()) && !req.getColumn().trim().isEmpty() &&
                (req.getOrder().equalsIgnoreCase("asc")|| req.getOrder().equalsIgnoreCase("desc")) &&
                ObjectUtil.isNotNull(req.getOrder()) &&!req.getOrder().trim().isEmpty()) {
            //修改字段，和数据库字段进行统一
            req.setColumn(req.getColumn().replaceAll("[A-Z]", "_$0").toLowerCase());
            req.setOrder(req.getOrder().toLowerCase());
        }
        LambdaQueryWrapper<BussinessInventory> wrapper = createWrapper(req);


        // 使用 PageHelper 开始分页
//        Page<BussinessInventory> page = PageFactory.getDefaultPage(Long.parseLong(req.getPageNo()),Long.parseLong(req.getPageSize()));
        Page<BussinessInventory> page = this.page(PageFactory.getDefaultPage(Long.valueOf(req.getPageNo()),Long.valueOf(req.getPageSize())), wrapper);

      return   PageResultFactory.createPageResult(page);

    }



    /**
     * 设置单据单号
     * 通用方法，根据组织机构id以及业务单据类型来进行设置
     * @param
     */
    public OrderNum setOrderCode(String bussinessType,Long orgId){
        //设置采购单号，需要先判断该组织机构的采购单号是否存在，如果存在则将数量进行增加，如果不存在则新增一条对应的数据
        OrderNum orderNum = new OrderNum();
        orderNum.setYear(LocalDateTime.now().getYear());
        orderNum.setBussinessType(bussinessType);
        orderNum.setOrgId(orgId);
        //将业务类型转为中文简写
        Long sysDictId = sysDictService.getOne(new LambdaQueryWrapper<SysDict>()
                .eq(SysDict::getDictCode, "busstype_chinese")).getDictId();

        String itemValue = sysDictItemService.getOne(new LambdaQueryWrapper<SysDictItem>()
                .eq(SysDictItem::getItemText, bussinessType)
                .eq(SysDictItem::getDictId,sysDictId)).getItemValue();
        orderNum.setBussinessType(itemValue);
        OrderNum one = orderNumService.getOne(new LambdaQueryWrapper<OrderNum>()
                .eq(OrderNum::getOrgId, orderNum.getOrgId())
                .eq(OrderNum::getBussinessType, orderNum.getBussinessType())
                .eq(OrderNum::getYear, orderNum.getYear()));
        //设置num的数量
        if (ObjectUtil.isNull(one)){
            orderNum.setNum(1);
            orderNumService.save(orderNum);
            return orderNum;
        }else {
            one.setNum(one.getNum()+1);
            orderNumService.updateById(one);
            return one;
        }
    }

    private LambdaQueryWrapper<BussinessInventory> createWrapper(BussinessInventoryReq req) {
        LambdaQueryWrapper<BussinessInventory> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isEmpty(req)) {
            return wrapper;
        }
//        wrapper.eq(BussinessInventory::getResult, req.getResult());
        wrapper.eq(BussinessInventory::getOrgId, req.getOrgId());
        wrapper.eq(ObjectUtil.isNotNull(req.getResult())&& !req.getResult().equals("all") ,BussinessInventory::getResult,req.getResult());
        wrapper.eq(StringUtils.isNotBlank(req.getWarehouseId()), BussinessInventory::getWarehouseId, req.getWarehouseId());
        wrapper.eq(StringUtils.isNotBlank(req.getInventoryState()), BussinessInventory::getInventoryState, req.getInventoryState());
        if (StringUtils.isNotBlank(req.getExamineState())) {
            if (req.getExamineState().equals("unaudited")) {
                wrapper.and(
                        i -> i.eq(BussinessInventory::getExamineState, "none")
                                .or()
                                .eq(BussinessInventory::getExamineState, "working")
                );
            }
            else
            {
                wrapper.eq( BussinessInventory::getExamineState, "finished");
            }
        }
        wrapper.eq(StringUtils.isNotBlank(req.getInventoryType()), BussinessInventory::getInventoryType, req.getInventoryType());
        wrapper.orderByDesc(BussinessInventory::getUpdateTime);

        return wrapper;
    }

}