import { ok, type ReadonlyDB } from "@tailor-platform/erp-kit/core";
import { Decimal } from "decimal.js";
import type { DB } from "../generated/kysely-tailordb";

export interface ListPurchaseReceiptQuantitiesForMatchingInput {
  purchaseOrderLineIds: string[];
}

export interface PurchaseReceiptQuantityForMatching {
  purchaseOrderLineId: string;
  receivedQuantity: string;
}

export async function run(
  db: ReadonlyDB<DB>,
  input: ListPurchaseReceiptQuantitiesForMatchingInput,
) {
  if (input.purchaseOrderLineIds.length === 0) {
    return ok({ receiptQuantities: [] as PurchaseReceiptQuantityForMatching[] });
  }

  const receiptLines = await db
    .selectFrom("InventoryExecutionLine")
    .innerJoin(
      "InventoryExecution",
      "InventoryExecution.id",
      "InventoryExecutionLine.inventoryExecutionId",
    )
    .select([
      "InventoryExecutionLine.sourceLineId as purchaseOrderLineId",
      "InventoryExecutionLine.quantity as quantity",
    ])
    .where("InventoryExecutionLine.sourceLineId", "in", input.purchaseOrderLineIds)
    .where("InventoryExecutionLine.direction", "=", "IN")
    .where("InventoryExecution.executionType", "=", "GOODS_RECEIPT")
    .where("InventoryExecution.status", "=", "POSTED")
    .where("InventoryExecution.sourceDocumentType", "=", "PURCHASE_ORDER")
    .execute();

  const quantityByLineId = new Map<string, Decimal>();
  for (const row of receiptLines) {
    if (row.purchaseOrderLineId === null) continue;
    quantityByLineId.set(
      row.purchaseOrderLineId,
      (quantityByLineId.get(row.purchaseOrderLineId) ?? new Decimal(0)).plus(row.quantity),
    );
  }

  return ok({
    receiptQuantities: [...quantityByLineId.entries()].map(([purchaseOrderLineId, quantity]) => ({
      purchaseOrderLineId,
      receivedQuantity: quantity.toString(),
    })),
  });
}
