package net.lab1024.sa.admin.module.business.receive;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import net.lab1024.sa.admin.module.business.base.item.domain.entity.ItemEntity;
import net.lab1024.sa.admin.module.business.base.item.service.ItemQueryService;
import net.lab1024.sa.admin.module.business.base.location.dao.LocationDao;
import net.lab1024.sa.admin.module.business.base.location.domain.entity.LocationEntity;
import net.lab1024.sa.admin.module.business.base.location.service.LocationQueryService;
import net.lab1024.sa.admin.module.business.base.stock.dao.StockDao;
import net.lab1024.sa.admin.module.business.base.stock.domain.entity.StockEntity;
import net.lab1024.sa.admin.module.business.base.stock.service.StockQueryService;
import net.lab1024.sa.admin.module.business.inventory.domain.entity.InventoryEntity;
import net.lab1024.sa.admin.module.business.inventory.manager.InventoryManager;
import net.lab1024.sa.admin.module.business.inventory.service.InventoryQueryService;
import net.lab1024.sa.admin.module.business.inventory.service.InventoryService;
import net.lab1024.sa.admin.module.business.itemKey.domain.entity.ItemKeyEntity;
import net.lab1024.sa.admin.module.business.itemKey.manager.ItemKeyManager;
import net.lab1024.sa.admin.module.business.itemKey.service.ItemKeyQueryService;
import net.lab1024.sa.admin.module.business.itemKey.service.ItemKeyService;
import net.lab1024.sa.admin.module.business.receive.asn.domain.entity.AsnEntity;
import net.lab1024.sa.admin.module.business.receive.asn.service.AsnQueryService;
import net.lab1024.sa.admin.module.business.receive.asnDetail.domain.entity.AsnDetailEntity;
import net.lab1024.sa.admin.module.business.receive.asnDetail.domain.vo.AsnDetailVO;
import net.lab1024.sa.admin.module.business.receive.asnDetail.manager.AsnDetailManager;
import net.lab1024.sa.admin.module.business.receive.asnDetail.service.AsnDetailQueryService;
import net.lab1024.sa.admin.module.business.receive.asnDetail.service.AsnDetailService;
import net.lab1024.sa.admin.module.business.task.constant.TaskStatusEnum;
import net.lab1024.sa.admin.module.business.task.constant.TaskTypeEnum;
import net.lab1024.sa.admin.module.business.task.domain.entity.TaskEntity;
import net.lab1024.sa.admin.module.business.task.manager.TaskManager;
import net.lab1024.sa.admin.module.business.task.service.TaskService;
import net.lab1024.sa.admin.util.JoinerResult;
import net.lab1024.sa.admin.util.ResponseDTOUtils;
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.common.util.SmartRequestUtil;
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.*;

@Service
public class ReceiveService {

    @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 AsnQueryService asnQueryService;

    @Resource
    private AsnDetailQueryService asnDetailQueryService;

    @Resource
    private InventoryQueryService inventoryQueryService;

    @Resource
    private AsnDetailService asnDetailService;

    @Resource
    private ItemKeyService itemKeyService;

    @Resource
    private TaskService taskService;

    @Resource
    private InventoryService inventoryService;

    @Resource
    private SerialNumberService serialNumberService;


    /**
     * 批量收货
     *
     * @param idList 入库明细id集合
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> batchReceive(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return ResponseDTO.userErrorParam(UserErrorCode.PARAM_ERROR.getMsg());
        }
        List<AsnDetailEntity> asnDetails = asnDetailQueryService.queryAsnDetailList(idList);
        if (CollectionUtils.isEmpty(asnDetails)) {
            return ResponseDTO.userErrorParam(UserErrorCode.PARAM_ERROR.getMsg());
        }

        return batchReceive(asnDetails, null, null);

    }

    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseDTO<String> batchReceive(List<AsnDetailEntity> asnDetails, String stockCode, String locationCode) {
        //消息提示
        JoinerResult joiner = JoinerResult.createJoiner();

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

        //查询入库单
        List<Long> asnIds = asnDetails.stream().map(AsnDetailEntity::getAsnId).distinct().toList();
        Map<Long, AsnEntity> asnMap = asnQueryService.queryAsnListToMap(asnIds);

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

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

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

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

            //入库单
            AsnEntity asn = asnMap.get(asnDetail.getAsnId());

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

            if (asnDetail.getReceivedQuantity().compareTo(asnDetail.getOrderQuantity()) > 0) {
                joiner.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);
            insertToTask.add(task);

            //生成库存
            InventoryEntity inventory = inventoryQueryService.queryInventory(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);
            }

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

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

        //刷新入库单
        asnIds.forEach(asnDetailService::refreshAsn);

        return ResponseDTOUtils.buildResponseDTO(joiner);
    }

    /**
     * 批量更新或新增
     *
     * @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);
        }

    }


}
