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

export interface PostIssueInput {
  readonly tenantId: string
  readonly itemId: string
  readonly locationId: string
  readonly qty: number
  readonly holderRef?: string
  readonly occurredAt: Date
  readonly method: 'fifo' | 'weighted_average'
  readonly allowNegative?: boolean
}

export async function postIssue(
  db: Database<InventorySchema> | Transaction<InventorySchema>,
  input: PostIssueInput,
): Promise<MovementResult> {
  return withInventoryTransaction(db, async (tx) => {
    const rows = await tx
      .select({ method: stockItem.method })
      .from(stockItem)
      .where(and(eq(stockItem.tenantId, input.tenantId), eq(stockItem.id, input.itemId)))
      .limit(1)

    const storedMethod = rows[0]?.method as 'fifo' | 'weighted_average' | undefined
    if (storedMethod && storedMethod !== input.method) {
      throw new InventoryValidationError('method')
    }

    return postMovement(tx, {
      tenantId: input.tenantId,
      itemId: input.itemId,
      locationId: input.locationId,
      kind: 'issue',
      qtyDelta: -input.qty,
      holderRef: input.holderRef,
      occurredAt: input.occurredAt,
      allowNegative: input.allowNegative,
    })
  })
}
