import { InventoryValidationError } from './errors.js'
import type { Database, Transaction } from '@platform-modules/db'
import type { InventorySchema } from './schema.js'
import type { TransferResult } from './types.js'
import { postMovement } from './internal/post-movement.js'
import { withInventoryTransaction } from './internal/public-helpers.js'

export interface TransferStockInput {
  readonly tenantId: string
  readonly itemId: string
  readonly fromLocationId: string
  readonly toLocationId: string
  readonly qty: number
  readonly holderRef: string
  readonly occurredAt: Date
}

export async function transferStock(
  db: Database<InventorySchema> | Transaction<InventorySchema>,
  input: TransferStockInput,
): Promise<TransferResult> {
  if (input.fromLocationId === input.toLocationId) {
    throw new InventoryValidationError('toLocationId')
  }

  return withInventoryTransaction(db, async (tx) => {
    const transferGroup = crypto.randomUUID()
    const transferOut = await postMovement(tx, {
      tenantId: input.tenantId,
      itemId: input.itemId,
      locationId: input.fromLocationId,
      kind: 'transfer_out',
      qtyDelta: -input.qty,
      holderRef: input.holderRef,
      transferGroup,
      occurredAt: input.occurredAt,
      allowNegative: false,
    })

    const unitCost = Number(transferOut.movement.unitCost ?? 0)
    const transferIn = await postMovement(tx, {
      tenantId: input.tenantId,
      itemId: input.itemId,
      locationId: input.toLocationId,
      kind: 'transfer_in',
      qtyDelta: input.qty,
      unitCost,
      holderRef: input.holderRef,
      transferGroup,
      occurredAt: input.occurredAt,
    })

    return {
      transferOut: transferOut.movement,
      transferIn: transferIn.movement,
    }
  })
}
