"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadByQty = void 0;
const typeorm_1 = require("typeorm");
const uuid_1 = require("uuid");
const sales_base_1 = require("@things-factory/sales-base");
const worksheet_base_1 = require("@things-factory/worksheet-base");
const warehouse_base_1 = require("@things-factory/warehouse-base");
exports.loadByQty = {
    async loadByQty(_, { worksheetDetailPatch }, context) {
        var _a, _b, _c;
        try {
            const { domain, user, tx } = context.state;
            console.time('load');
            const updatedWorksheetDetails = worksheetDetailPatch.orderInventories;
            const releaseGoodNo = worksheetDetailPatch.releaseGoodNo;
            const releaseGood = await tx.getRepository(sales_base_1.ReleaseGood).findOne({
                where: { domain, name: releaseGoodNo },
                relations: ['bizplace', 'orderInventories']
            });
            if (!releaseGood) {
                throw new Error('Release good not found');
            }
            const worksheet = await tx.getRepository(worksheet_base_1.Worksheet).findOne({
                where: {
                    domain,
                    releaseGood,
                    type: worksheet_base_1.WORKSHEET_TYPE.LOADING,
                    status: (0, typeorm_1.In)([
                        worksheet_base_1.WORKSHEET_STATUS.EXECUTING,
                        worksheet_base_1.WORKSHEET_STATUS.PARTIAL_EXECUTING
                    ])
                },
                relations: ['worksheetDetails', 'worksheetDetails.targetInventory', 'worksheetDetails.domain']
            });
            if (!worksheet) {
                throw new Error('No loading worksheet found for order ' + releaseGoodNo);
            }
            const oiIds = worksheet.worksheetDetails.map((wsd) => wsd.targetInventory.id);
            const orderInventories = await tx.getRepository(sales_base_1.OrderInventory).find({
                where: { id: (0, typeorm_1.In)(oiIds) },
                relations: [
                    'inventory',
                    'domain',
                    'bizplace',
                    'releaseGood',
                    'product',
                    'productDetail',
                    'binLocation',
                    'orderProduct'
                ]
            });
            const updatedOrderInventories = [];
            for (const wsd of updatedWorksheetDetails) {
                // Check if this is combined data with multiple order inventory references
                // (from bin scan flow with combineSameProductsWithAllRefs)
                if (wsd.allRelatedOrderInvs && wsd.allRelatedOrderInvs.length > 0) {
                    // Combined mode: distribute loadedQty across multiple order inventories (FIFO)
                    let remainingLoadQty = wsd.loadedQty;
                    for (const ref of wsd.allRelatedOrderInvs) {
                        if (remainingLoadQty <= 0)
                            break;
                        let orderInventory = orderInventories.find(oi => oi.id === ref.id);
                        if (!orderInventory)
                            continue;
                        const foundWorksheetDetail = worksheet.worksheetDetails.find(foundWsd => foundWsd.targetInventory.id === orderInventory.id);
                        if (!foundWorksheetDetail)
                            continue;
                        // Skip if already loaded or DO generated
                        if (orderInventory.status === sales_base_1.ORDER_INVENTORY_STATUS.LOADED || orderInventory.deliveryOrderId !== null) {
                            continue;
                        }
                        // Calculate how much to load from this order inventory
                        const availableQty = orderInventory.pickedQty;
                        const qtyToLoad = Math.min(remainingLoadQty, availableQty);
                        remainingLoadQty -= qtyToLoad;
                        if (qtyToLoad === orderInventory.releaseQty) {
                            // Full load - mark as LOADED
                            orderInventory = Object.assign(Object.assign({}, orderInventory), { status: sales_base_1.ORDER_INVENTORY_STATUS.LOADED, updater: user, updatedAt: new Date() });
                            await tx.getRepository(worksheet_base_1.WorksheetDetail).update(foundWorksheetDetail.id, {
                                status: worksheet_base_1.WORKSHEET_STATUS.DONE,
                                updater: user,
                                updatedAt: new Date()
                            });
                        }
                        else if (qtyToLoad < orderInventory.releaseQty && qtyToLoad > 0) {
                            // Partial load - split order inventory
                            const remainingOiQty = orderInventory.releaseQty - qtyToLoad;
                            const newOrderInventory = tx.getRepository(sales_base_1.OrderInventory).create(Object.assign(Object.assign({}, orderInventory), { id: undefined, name: sales_base_1.OrderNoGenerator.orderInventory(), releaseQty: remainingOiQty, releaseUomValue: (orderInventory.releaseUomValue / orderInventory.releaseQty) * remainingOiQty, pickedQty: orderInventory.pickedQty - qtyToLoad, sortedQty: orderInventory.sortedQty === 0 ? 0 : orderInventory.sortedQty - qtyToLoad, status: orderInventory.status, updater: user, updatedAt: new Date() }));
                            await tx.getRepository(sales_base_1.OrderInventory).save(newOrderInventory);
                            const newWorksheetDetail = tx.getRepository(worksheet_base_1.WorksheetDetail).create(Object.assign(Object.assign({}, foundWorksheetDetail), { id: undefined, name: `LOAD-DETAIL-` + (0, uuid_1.v4)(), worksheet: worksheet, targetInventory: newOrderInventory, status: worksheet_base_1.WORKSHEET_STATUS.EXECUTING, updater: user, updatedAt: new Date() }));
                            await tx.getRepository(worksheet_base_1.WorksheetDetail).save(newWorksheetDetail);
                            orderInventory = Object.assign(Object.assign({}, orderInventory), { status: sales_base_1.ORDER_INVENTORY_STATUS.LOADED, releaseUomValue: (orderInventory.releaseUomValue / orderInventory.releaseQty) * qtyToLoad, releaseQty: qtyToLoad, pickedQty: qtyToLoad, sortedQty: qtyToLoad, updater: user, updatedAt: new Date() });
                            await tx.getRepository(worksheet_base_1.WorksheetDetail).update(foundWorksheetDetail.id, {
                                status: worksheet_base_1.WORKSHEET_STATUS.DONE,
                                updater: user,
                                updatedAt: new Date()
                            });
                        }
                        else {
                            // qtyToLoad is 0, skip this order inventory
                            continue;
                        }
                        const inventory = await tx.getRepository(warehouse_base_1.Inventory).findOne({
                            where: { id: orderInventory.inventoryId }
                        });
                        await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.LOADING, 0, 0, user, tx);
                        updatedOrderInventories.push(orderInventory);
                    }
                    // Validate that all requested quantity was loaded
                    if (remainingLoadQty > 0) {
                        console.warn(`Could not fully distribute loadedQty for SKU ${wsd.productSku}. Remaining: ${remainingLoadQty}`);
                    }
                }
                else {
                    // Standard mode: single order inventory reference
                    // Support both:
                    // 1. Match by worksheetDetail name (when using LOADING_WORKSHEET_V2 query)
                    // 2. Match by relatedOrderInv.id (when name is null)
                    let foundWorksheetDetail;
                    let orderInventory;
                    if (wsd.name) {
                        foundWorksheetDetail = worksheet.worksheetDetails.find(foundWsd => foundWsd.name === wsd.name);
                        if (foundWorksheetDetail) {
                            orderInventory = orderInventories.find(oi => oi.id === foundWorksheetDetail.targetInventory.id);
                        }
                    }
                    if (!foundWorksheetDetail && ((_a = wsd.relatedOrderInv) === null || _a === void 0 ? void 0 : _a.id)) {
                        orderInventory = orderInventories.find(oi => oi.id === wsd.relatedOrderInv.id);
                        if (orderInventory) {
                            foundWorksheetDetail = worksheet.worksheetDetails.find(foundWsd => foundWsd.targetInventory.id === orderInventory.id);
                        }
                    }
                    if (!foundWorksheetDetail || !orderInventory) {
                        console.warn(`Could not find worksheet detail or order inventory for item: ${JSON.stringify({ name: wsd.name, relatedOrderInvId: (_b = wsd.relatedOrderInv) === null || _b === void 0 ? void 0 : _b.id, productSku: wsd.productSku })}`);
                        continue;
                    }
                    if (orderInventory.status === sales_base_1.ORDER_INVENTORY_STATUS.LOADED || orderInventory.deliveryOrderId !== null) {
                        continue;
                    }
                    if (wsd.loadedQty > orderInventory.pickedQty) {
                        throw new Error('Load qty is more than picked qty for sku ' + wsd.productSku);
                    }
                    else if (wsd.loadedQty == orderInventory.releaseQty) {
                        orderInventory = Object.assign(Object.assign({}, orderInventory), { status: sales_base_1.ORDER_INVENTORY_STATUS.LOADED, updater: user, updatedAt: new Date() });
                        await tx.getRepository(worksheet_base_1.WorksheetDetail).update(foundWorksheetDetail.id, {
                            status: worksheet_base_1.WORKSHEET_STATUS.DONE,
                            updater: user,
                            updatedAt: new Date()
                        });
                    }
                    else if (wsd.loadedQty < orderInventory.releaseQty) {
                        const remainingQty = orderInventory.releaseQty - wsd.loadedQty;
                        const newOrderInventory = tx.getRepository(sales_base_1.OrderInventory).create(Object.assign(Object.assign({}, orderInventory), { id: undefined, name: sales_base_1.OrderNoGenerator.orderInventory(), releaseQty: remainingQty, releaseUomValue: (orderInventory.releaseUomValue / orderInventory.releaseQty) * remainingQty, pickedQty: orderInventory.pickedQty - wsd.loadedQty, sortedQty: orderInventory.sortedQty === 0 ? 0 : orderInventory.sortedQty - wsd.loadedQty, status: orderInventory.status, updater: user, updatedAt: new Date() }));
                        await tx.getRepository(sales_base_1.OrderInventory).save(newOrderInventory);
                        const newWorksheetDetail = tx.getRepository(worksheet_base_1.WorksheetDetail).create(Object.assign(Object.assign({}, foundWorksheetDetail), { id: undefined, name: `LOAD-DETAIL-` + (0, uuid_1.v4)(), worksheet: worksheet, targetInventory: newOrderInventory, status: worksheet_base_1.WORKSHEET_STATUS.EXECUTING, updater: user, updatedAt: new Date() }));
                        await tx.getRepository(worksheet_base_1.WorksheetDetail).save(newWorksheetDetail);
                        orderInventory = Object.assign(Object.assign({}, orderInventory), { status: sales_base_1.ORDER_INVENTORY_STATUS.LOADED, releaseUomValue: (orderInventory.releaseUomValue / orderInventory.releaseQty) * wsd.loadedQty, releaseQty: wsd.loadedQty, pickedQty: wsd.loadedQty, sortedQty: wsd.loadedQty, updater: user, updatedAt: new Date() });
                        await tx.getRepository(worksheet_base_1.WorksheetDetail).update(foundWorksheetDetail.id, {
                            status: worksheet_base_1.WORKSHEET_STATUS.DONE,
                            updater: user,
                            updatedAt: new Date()
                        });
                    }
                    const inventory = await tx.getRepository(warehouse_base_1.Inventory).findOne({
                        where: { id: orderInventory.inventoryId }
                    });
                    await (0, warehouse_base_1.generateInventoryHistory)(inventory, releaseGood, warehouse_base_1.INVENTORY_TRANSACTION_TYPE.LOADING, 0, 0, user, tx);
                    updatedOrderInventories.push(orderInventory);
                }
            }
            if (updatedOrderInventories.length < 1) {
                return false;
            }
            else {
                const deliveryOrder = {
                    truckNo: worksheetDetailPatch === null || worksheetDetailPatch === void 0 ? void 0 : worksheetDetailPatch.vehicleNo,
                    ownCollection: worksheetDetailPatch === null || worksheetDetailPatch === void 0 ? void 0 : worksheetDetailPatch.ownCollection,
                    totalPalletQty: worksheetDetailPatch === null || worksheetDetailPatch === void 0 ? void 0 : worksheetDetailPatch.palletQty,
                    contactPointRefId: releaseGood.deliverToId || ((_c = releaseGood.deliverTo) === null || _c === void 0 ? void 0 : _c.id) || null
                };
                const createdDo = await (0, sales_base_1.generateDeliveryOrder)(deliveryOrder, updatedOrderInventories, releaseGood.bizplace, releaseGood, domain, user, tx);
                return true;
            }
        }
        catch (e) {
            throw e;
        }
    }
};
//# sourceMappingURL=load-by-qty.js.map