import {
  reserve as moduleReserve,
  setInventory as moduleSetInventory,
  release as moduleRelease,
  consume as moduleConsume,
  commitStock as moduleCommitStock,
  sweepStaleReservations,
  pushSchema,
  isOversoldError,
  isInventoryItemNotFoundError,
  isInventoryValidationError,
  stockReservation,
  type InventorySchema,
} from '@platform-modules/commerce-inventory';
import type { Transaction, TransactionalDatabase } from '@platform-modules/db';
import type { DrizzleClient, DrizzleDb } from '@/server/db/client';
import {
  asSkuId,
  asStockReservationId,
  asVendorId,
  toModuleRef,
} from '@/server/platform-seams/ids.js';

export function toInventoryDb(db: DrizzleDb): TransactionalDatabase<InventorySchema> {
  return db as unknown as TransactionalDatabase<InventorySchema>;
}

/** Cast a host transaction to Transaction<InventorySchema> for module calls inside host tx blocks. */
export function toInventoryTx(tx: DrizzleClient): Transaction<InventorySchema> {
  return tx as unknown as Transaction<InventorySchema>;
}

export async function setInventory(
  tx: Transaction<InventorySchema>,
  item: Parameters<typeof moduleSetInventory>[1],
): ReturnType<typeof moduleSetInventory> {
  return moduleSetInventory(tx, {
    ...item,
    skuId: toModuleRef(asSkuId(item.skuId)),
    vendorId: item.vendorId == null ? item.vendorId : toModuleRef(asVendorId(item.vendorId)),
  });
}

export async function reserve(
  tx: Transaction<InventorySchema>,
  args: Parameters<typeof moduleReserve>[1],
): ReturnType<typeof moduleReserve> {
  return moduleReserve(tx, { ...args, skuId: toModuleRef(asSkuId(args.skuId)) });
}

export async function consume(
  tx: Transaction<InventorySchema>,
  reservationId: string,
): ReturnType<typeof moduleConsume> {
  return moduleConsume(tx, toModuleRef(asStockReservationId(reservationId)));
}

export async function release(
  tx: Transaction<InventorySchema>,
  reservationId: string,
): ReturnType<typeof moduleRelease> {
  return moduleRelease(tx, toModuleRef(asStockReservationId(reservationId)));
}

export async function commitStock(
  tx: Transaction<InventorySchema>,
  skuId: string,
  qty: number,
): ReturnType<typeof moduleCommitStock> {
  return moduleCommitStock(tx, toModuleRef(asSkuId(skuId)), qty);
}

export {
  sweepStaleReservations,
  pushSchema,
  isOversoldError,
  isInventoryItemNotFoundError,
  isInventoryValidationError,
  stockReservation,
};
export type { InventorySchema };
