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

export interface GetStockLevelInput {
  itemId: string;
  storageLocationId: string;
}

export async function run(db: ReadonlyDB<DB>, input: GetStockLevelInput) {
  const stockLevels = await db
    .selectFrom("StockLevel")
    .selectAll()
    .where("itemId", "=", input.itemId)
    .where("storageLocationId", "=", input.storageLocationId)
    .execute();

  if (stockLevels.length === 0) {
    return ok({ stockLevel: null });
  }

  const available = stockLevels.find((row) => row.stockType === "AVAILABLE");
  const blocked = stockLevels.find((row) => row.stockType === "BLOCKED");
  const inTransit = stockLevels.find((row) => row.stockType === "IN_TRANSIT");
  const reservationsResult = await db
    .selectFrom("StockReservation")
    .selectAll()
    .where("itemId", "=", input.itemId)
    .where("storageLocationId", "=", input.storageLocationId)
    .where("status", "=", "OPEN")
    .execute();
  const reservations = Array.isArray(reservationsResult)
    ? reservationsResult
    : reservationsResult
      ? [reservationsResult]
      : [];

  const onHand = new Decimal(available?.quantity ?? 0).plus(blocked?.quantity ?? 0);
  const reservedQuantity = sumOpenStockReservationQuantity(reservations);
  const blockedQuantity = new Decimal(blocked?.quantity ?? 0);
  const availableQuantity = new Decimal(available?.quantity ?? 0)
    .minus(reservedQuantity)
    .toString();

  return ok({
    stockLevel: {
      itemId: input.itemId,
      storageLocationId: input.storageLocationId,
      onHand: onHand.toString(),
      reserved: reservedQuantity.toString(),
      blocked: blockedQuantity.toString(),
      inTransit: new Decimal(inTransit?.quantity ?? 0).toString(),
      availableQuantity,
      stockLevels,
      reservation: reservations[0] ?? null,
    },
  });
}
