package net.lab1024.sa.admin.module.business.wms.shipping.service.impl;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.wms.base.item.domain.entity.ItemEntity;
import net.lab1024.sa.admin.module.business.wms.base.item.manager.ItemManager;
import net.lab1024.sa.admin.module.business.wms.base.item.service.ItemQueryService;
import net.lab1024.sa.admin.module.business.wms.base.location.domain.entity.LocationEntity;
import net.lab1024.sa.admin.module.business.wms.base.location.manager.LocationManager;
import net.lab1024.sa.admin.module.business.wms.base.stock.domain.entity.StockEntity;
import net.lab1024.sa.admin.module.business.wms.base.stock.manager.StockManager;
import net.lab1024.sa.admin.module.business.wms.inventory.inventory.domain.entity.InventoryEntity;
import net.lab1024.sa.admin.module.business.wms.inventory.inventory.manager.InventoryManager;
import net.lab1024.sa.admin.module.business.wms.inventory.inventory.service.InventoryQueryService;
import net.lab1024.sa.admin.module.business.wms.shipping.form.AllocationForm;
import net.lab1024.sa.admin.module.business.wms.shipping.pick.domain.entity.PickEntity;
import net.lab1024.sa.admin.module.business.wms.shipping.pick.manager.PickManager;
import net.lab1024.sa.admin.module.business.wms.shipping.pickDetail.domain.entity.PickDetailEntity;
import net.lab1024.sa.admin.module.business.wms.shipping.pickDetail.manager.PickDetailManager;
import net.lab1024.sa.admin.module.business.wms.shipping.pickDetail.service.PickDetailService;
import net.lab1024.sa.admin.module.business.wms.shipping.service.ShippingService;
import net.lab1024.sa.admin.module.business.wms.task.constant.TaskStatusEnum;
import net.lab1024.sa.admin.module.business.wms.task.constant.TaskTypeEnum;
import net.lab1024.sa.admin.module.business.wms.task.domain.entity.TaskEntity;
import net.lab1024.sa.admin.module.business.wms.task.manager.TaskManager;
import net.lab1024.sa.admin.module.business.wms.task.service.TaskService;
import net.lab1024.sa.admin.util.JoinerResult;
import net.lab1024.sa.admin.util.ResponseDTOUtil;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBigDecimalUtil;
import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService;
import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberIdEnum;
import net.lab1024.sa.base.module.support.serialnumber.service.SerialNumberService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ShippingServiceImpl implements ShippingService {

    @Resource
    private LocationManager locationManager;

    @Resource
    private StockManager stockManager;

    @Resource
    private PickManager pickManager;

    @Resource
    private PickDetailManager pickDetailManager;

    @Resource
    private TaskManager taskManager;

    @Resource
    private InventoryManager inventoryManager;

    @Resource
    private ItemQueryService itemQueryService;

    @Resource
    private InventoryQueryService inventoryQueryService;

    @Resource
    private PickDetailService pickDetailService;

    @Resource
    private TaskService taskService;

    @Resource
    private SerialNumberService serialNumberService;

    @Resource
    private DataTracerService dataTracerService;


    /**
     * 分配明细
     *
     * @param allocationForm 分配明细参数
     * @return resultMsg
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> allocationPickDetail(AllocationForm allocationForm) {
        Long startTime = System.currentTimeMillis();

        //消息提示
        JoinerResult resultMsg = JoinerResult.createJoiner();

        //出库单
        PickEntity pick = pickManager.getById(allocationForm.getPickId());

        //出库单明细
        List<PickDetailEntity> pickDetails = pickDetailManager.listByIds(allocationForm.getPickDetailIds());

        //查询物料
        List<Long> itemIds = pickDetails.stream().map(PickDetailEntity::getItemId).toList();
        Map<Long, ItemEntity> itemMap = itemQueryService.queryByItemIdsToMap(itemIds);

        //查询库存
        List<InventoryEntity> inventoryList = inventoryQueryService.queryInventoryByItemIds(itemIds);
        if (inventoryList.isEmpty()) {
            List<String> codes = itemMap.values().stream().map(ItemEntity::getItemCode).toList();
            resultMsg.getErrorMsg().add(codes + "物料库存不足，请先补充库存！");
            return ResponseDTOUtil.buildResponseDTO(resultMsg);
        }

        List<InventoryEntity> updateToInventory = new ArrayList<>();
        List<PickDetailEntity> updateToPickDetail = new ArrayList<>();
        List<TaskEntity> createToTask = new ArrayList<>();

        for (PickDetailEntity pickDetail : pickDetails) {
            //物料
            ItemEntity item = itemMap.get(pickDetail.getItemId());

            BigDecimal unQty = SmartBigDecimalUtil.subtract(pickDetail.getOrderQuantity(), pickDetail.getAllocatedQuantity(), 2);
            if (unQty.compareTo(BigDecimal.ZERO) == 0) {
                resultMsg.getErrorMsg().add(item.getItemCode() + "物料已分配,请勿重复操作！");
                continue;
            }
            //分配数量
            BigDecimal allocateQty = BigDecimal.ZERO;

            //库存
            for (InventoryEntity inventory : inventoryList) {
                //库存可用数量
                allocateQty = SmartBigDecimalUtil.subtract(inventory.getQuantity(), inventory.getQueuedQuantity(), 2);
                if (allocateQty.compareTo(BigDecimal.ZERO) <= 0) {
                    continue;
                }
                if (unQty.compareTo(allocateQty) < 0) {
                    allocateQty = unQty;
                }
                //更新库存占用数量
                inventory.setQueuedQuantity(SmartBigDecimalUtil.add(inventory.getQueuedQuantity(), allocateQty, 2));
                updateToInventory.add(inventory);
                //更新明细分配数量
                pickDetail.setAllocatedQuantity(SmartBigDecimalUtil.add(pickDetail.getAllocatedQuantity(), allocateQty, 2));
                updateToPickDetail.add(pickDetail);
                //容器
                StockEntity stock = stockManager.queryStock(inventory.getStockId());
                //库位
                LocationEntity location = locationManager.queryLocation(inventory.getLocationId());
                //生成分配任务
                TaskEntity task = taskService.createTask(serialNumberService.generate(SerialNumberIdEnum.TASK), TaskStatusEnum.CREATED.getValue(), TaskTypeEnum.PICK.getValue(), pickDetail.getOrderQuantity(), inventory.getItemKeyId(), null, pickDetail.getPickDetailId(), stock, null, location, null, null, null);
                createToTask.add(task);
                unQty = SmartBigDecimalUtil.subtract(unQty, allocateQty, 2);
            }
            if (unQty.compareTo(BigDecimal.ZERO) > 0) {
                resultMsg.getErrorMsg().add(item.getItemCode() + "物料库存不足，无法完成分配！");
            } else {
                resultMsg.getSussMsg().add(item.getItemCode() + "物料分配成功");
            }
        }

        //批量操作
        if (CollectionUtils.isNotEmpty(updateToInventory)) {
            inventoryManager.updateBatchById(updateToInventory);
        }
        if (CollectionUtils.isNotEmpty(updateToPickDetail)) {
            pickDetailManager.updateBatchById(updateToPickDetail);
        }

        if (CollectionUtils.isNotEmpty(createToTask)) {
            taskManager.saveBatch(createToTask);
        }

        //刷新出库单
        pickDetailService.refreshPick(pick.getPickId());

        Long endTime = System.currentTimeMillis();
        log.info("分配明细耗时：{}ms", endTime - startTime);
        return ResponseDTOUtil.buildResponseDTO(resultMsg);
    }
}
