package net.lab1024.sa.admin.module.business.wms.receive.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.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.service.LocationQueryService;
import net.lab1024.sa.admin.module.business.wms.base.stock.domain.entity.StockEntity;
import net.lab1024.sa.admin.module.business.wms.base.stock.service.StockQueryService;
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.inventory.inventory.service.InventoryService;
import net.lab1024.sa.admin.module.business.wms.inventory.itemKey.domain.entity.ItemKeyEntity;
import net.lab1024.sa.admin.module.business.wms.inventory.itemKey.service.ItemKeyService;
import net.lab1024.sa.admin.module.business.wms.receive.asn.domain.entity.AsnEntity;
import net.lab1024.sa.admin.module.business.wms.receive.asn.manager.AsnManager;
import net.lab1024.sa.admin.module.business.wms.receive.asnDetail.domain.entity.AsnDetailEntity;
import net.lab1024.sa.admin.module.business.wms.receive.asnDetail.manager.AsnDetailManager;
import net.lab1024.sa.admin.module.business.wms.receive.asnDetail.service.AsnDetailQueryService;
import net.lab1024.sa.admin.module.business.wms.receive.asnDetail.service.AsnDetailService;
import net.lab1024.sa.admin.module.business.wms.receive.form.BatchReceiveForm;
import net.lab1024.sa.admin.module.business.wms.receive.form.BatchReturnForm;
import net.lab1024.sa.admin.module.business.wms.receive.service.ReceiveService;
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.TaskQueryService;
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.code.UserErrorCode;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartBigDecimalUtil;
import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum;
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 ReceiveServiceImpl implements ReceiveService {
    @Resource
    private AsnManager asnManager;

    @Resource
    private AsnDetailManager asnDetailManager;

    @Resource
    private TaskManager taskManager;

    @Resource
    private InventoryManager inventoryManager;

    @Resource
    private LocationQueryService locationQueryService;

    @Resource
    private StockQueryService stockQueryService;

    @Resource
    private ItemQueryService itemQueryService;

    @Resource
    private AsnDetailQueryService asnDetailQueryService;

    @Resource
    private TaskQueryService taskQueryService;

    @Resource
    private InventoryQueryService inventoryQueryService;

    @Resource
    private AsnDetailService asnDetailService;

    @Resource
    private ItemKeyService itemKeyService;

    @Resource
    private TaskService taskService;

    @Resource
    private InventoryService inventoryService;

    @Resource
    private SerialNumberService serialNumberService;

    @Resource
    private DataTracerService dataTracerService;


    /**
     * 批量收货
     *
     * @param batchReceiveForm 批量收货参数
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> batchReceive(BatchReceiveForm batchReceiveForm) {
        Long startTime = System.currentTimeMillis();
        List<AsnDetailEntity> asnDetails = asnDetailQueryService.queryByAsnDetailIds(batchReceiveForm.getAsnDetailIds());
        if (CollectionUtils.isEmpty(asnDetails)) {
            return ResponseDTO.userErrorParam(UserErrorCode.PARAM_ERROR.getMsg());
        }
        //消息提示
        JoinerResult resultMsg = JoinerResult.createJoiner();

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

        List<AsnDetailEntity> updateToAsnDetail = new ArrayList<>();
        List<TaskEntity> insertToTask = new ArrayList<>();
        List<InventoryEntity> insertToInventory = new ArrayList<>();
        List<InventoryEntity> updateToInventory = new ArrayList<>();

        //库位
        LocationEntity dstLocation = locationQueryService.queryByLocationCode(batchReceiveForm.getLocationCode());

        //容器
        StockEntity dstStock = stockQueryService.queryByStockCode(batchReceiveForm.getStockCode());

        //入库单
        AsnEntity asn = asnManager.getById(batchReceiveForm.getAsnId());

        for (AsnDetailEntity asnDetail : asnDetails) {
            //物料
            ItemEntity item = itemMap.get(asnDetail.getItemId());

            if (SmartBigDecimalUtil.subtract(asnDetail.getOrderQuantity(), asnDetail.getReceivedQuantity(), 2).compareTo(BigDecimal.ZERO) == 0) {
                resultMsg.getErrorMsg().add(item.getItemCode() + "明细已收货");
                continue;
            }

            if (asnDetail.getReceivedQuantity().compareTo(asnDetail.getOrderQuantity()) > 0) {
                resultMsg.getErrorMsg().add(item.getItemCode() + "收货数量不能大于订单数量");
                continue;
            }

            //更新入库明细
            asnDetail.setReceivedQuantity(SmartBigDecimalUtil.subtract(asnDetail.getOrderQuantity(), asnDetail.getReceivedQuantity(), 2));
            updateToAsnDetail.add(asnDetail);

            //获取itemKey
            ItemKeyEntity itemKey = itemKeyService.createItemKey(asn.getAsnNumber(), asnDetail.getItemId(), asnDetail.getPropC1());

            //生成入库记录
            TaskEntity task = taskService.createTask(serialNumberService.generate(SerialNumberIdEnum.TASK), TaskStatusEnum.CREATED.getValue(), TaskTypeEnum.ASN.getValue(), asnDetail.getOrderQuantity(), itemKey.getItemKeyId(), asnDetail.getAsnDetailId(), null, null, dstStock, null, dstLocation, null, null);
            task.setMoveQty(task.getPlanQty());
            if (SmartBigDecimalUtil.subtract(task.getPlanQty(), task.getMoveQty(), 2).compareTo(BigDecimal.ZERO) == 0) {
                task.setStatus(TaskStatusEnum.COMPLETED.getValue());
            } else {
                task.setStatus(TaskStatusEnum.IN_PROGRESS.getValue());
            }
            insertToTask.add(task);

            //生成库存记录
            InventoryEntity inventory = inventoryQueryService.queryInventoryByItemKeyId(itemKey.getItemKeyId());
            if (inventory == null) {
                inventory = inventoryService.createInventory(itemKey.getItemKeyId(), dstLocation == null ? null : dstLocation.getLocationId(), dstStock == null ? null : dstStock.getStockId(), asnDetail.getOrderQuantity());
                insertToInventory.add(inventory);
            } else {
                //库存数量累加
                inventory.setQuantity(SmartBigDecimalUtil.add(inventory.getQuantity(), asnDetail.getOrderQuantity(), 2));
                updateToInventory.add(inventory);
            }

            //生成库存日志

            resultMsg.getSussMsg().add(item.getItemCode() + "收货成功");
        }

        //批量操作
        batchUpdateOrInsert(updateToAsnDetail, insertToTask, insertToInventory, updateToInventory);

        //刷新入库单
        asnDetailService.refreshAsn(batchReceiveForm.getAsnId());

        //操作日志
        dataTracerService.addTrace(asn.getAsnId(), DataTracerTypeEnum.ASN, "批量收货：" + resultMsg.getSussMsg().toString() + resultMsg.getErrorMsg().toString());

        Long endTime = System.currentTimeMillis();
        log.info("批量收货耗时：{}ms", endTime - startTime);

        return ResponseDTOUtil.buildResponseDTO(resultMsg);
    }

    /**
     * 批量更新或新增
     *
     * @param updateToAsnDetail 入库明细
     * @param insertToTask      task
     * @param insertToInventory 新增库存
     * @param updateToInventory 更新库存
     */
    private void batchUpdateOrInsert(List<AsnDetailEntity> updateToAsnDetail, List<TaskEntity> insertToTask, List<InventoryEntity> insertToInventory, List<InventoryEntity> updateToInventory) {
        //批量更新入库明细
        if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
            asnDetailManager.updateBatchById(updateToAsnDetail);
        }

        //批量新增入库记录
        if (CollectionUtils.isNotEmpty(insertToTask)) {
            taskManager.saveBatch(insertToTask);
        }

        //批量新增库存
        if (CollectionUtils.isNotEmpty(insertToInventory)) {
            inventoryManager.saveBatch(insertToInventory);
        }

        //批量更新库存
        if (CollectionUtils.isNotEmpty(updateToInventory)) {
            inventoryManager.updateBatchById(updateToInventory);
        }

    }

    /**
     * 批量退货
     *
     * @param batchReturnForm 批量退货参数
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> batchReturn(BatchReturnForm batchReturnForm) {
        Long startTime = System.currentTimeMillis();
        List<TaskEntity> tasks = taskQueryService.queryByTaskIds(batchReturnForm.getTaskIds());
        if (CollectionUtils.isEmpty(tasks)) {
            return ResponseDTO.userErrorParam(UserErrorCode.PARAM_ERROR.getMsg());
        }

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

        //查询Task任务关联的所以入库明细
        List<Long> asnDetailIds = tasks.stream().map(TaskEntity::getAsnDetailId).toList();
        Map<Long, AsnDetailEntity> asnDetailMap = asnDetailQueryService.queryByAsnDetailIdsToMap(asnDetailIds);

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

        List<AsnDetailEntity> updateToAsnDetail = new ArrayList<>();
        List<TaskEntity> deleteToTask = new ArrayList<>();
        List<InventoryEntity> updateToInventory = new ArrayList<>();
        List<InventoryEntity> deleteToInventory = new ArrayList<>();

        for (TaskEntity task : tasks) {
            //物料
            ItemEntity item = itemMap.get(asnDetailMap.get(task.getAsnDetailId()).getItemId());

            //入库明细
            AsnDetailEntity asnDetail = asnDetailMap.get(task.getAsnDetailId());
            asnDetail.setReceivedQuantity(BigDecimal.ZERO);
            updateToAsnDetail.add(asnDetail);

            //删除task
            deleteToTask.add(task);

            //库存数退回
            InventoryEntity inventory = inventoryQueryService.queryInventoryByItemKeyId(task.getItemKeyId());
            if (inventory != null) {
                inventory.setQuantity(SmartBigDecimalUtil.subtract(inventory.getQuantity(), task.getPlanQty(), 2));
                if (inventory.getQuantity().compareTo(BigDecimal.ZERO) == 0) {
                    deleteToInventory.add(inventory);
                } else {
                    updateToInventory.add(inventory);
                }
            }
            //生成库存日志

            resultMsg.getSussMsg().add(item.getItemCode() + "退货成功");
        }
        //批量操作
        returnUpdateOrInsert(updateToAsnDetail, deleteToTask, updateToInventory, deleteToInventory);

        //刷新入库单
        asnDetailService.refreshAsn(batchReturnForm.getAsnId());

        //操作日志
        dataTracerService.addTrace(batchReturnForm.getAsnId(), DataTracerTypeEnum.ASN, "批量退货：" + resultMsg.getSussMsg().toString());

        Long endTime = System.currentTimeMillis();
        log.info("批量退货耗时：{}ms", endTime - startTime);

        return ResponseDTOUtil.buildResponseDTO(resultMsg);
    }

    /**
     * 批量更新或新增
     *
     * @param updateToAsnDetail 更新入库明细
     * @param deleteToTask      删除task
     * @param updateToInventory 更新库存
     * @param deleteToInventory 删除库存
     */
    private void returnUpdateOrInsert(List<AsnDetailEntity> updateToAsnDetail, List<TaskEntity> deleteToTask, List<InventoryEntity> updateToInventory, List<InventoryEntity> deleteToInventory) {
        //批量更新入库明细
        if (CollectionUtils.isNotEmpty(updateToAsnDetail)) {
            asnDetailManager.updateBatchById(updateToAsnDetail);
        }

        //批量删除入库记录
        if (CollectionUtils.isNotEmpty(deleteToTask)) {
            taskManager.removeBatchByIds(deleteToTask);
        }

        //批量更新库存
        if (CollectionUtils.isNotEmpty(updateToInventory)) {
            inventoryManager.updateBatchById(updateToInventory);
        }

        //批量删除库存
        if (CollectionUtils.isNotEmpty(deleteToInventory)) {
            inventoryManager.removeBatchByIds(deleteToInventory);
        }

    }


}
