import type { Database, Transaction } from '@platform-modules/db'
import { InventoryTransactionRequiredError } from '../errors.js'
import type { InventorySchema } from '../schema.js'
import type { Movement } from '../types.js'

type SqlRow = Record<string, unknown>

export function firstRows(result: unknown): SqlRow[] {
  return (Array.isArray(result) ? result : (result as { rows?: SqlRow[] }).rows) ?? []
}

export function firstRow(result: unknown): SqlRow | undefined {
  return firstRows(result)[0]
}

export function numericValue(value: unknown): number {
  return Number(value ?? 0)
}

export function textValue(value: unknown): string | null {
  return value === null || typeof value === 'undefined' ? null : String(value)
}

export function mapMovement(row: SqlRow): Movement {
  return {
    id: String(row.id),
    tenantId: String(row.tenant_id),
    itemId: String(row.item_id),
    locationId: String(row.location_id),
    kind: String(row.kind) as Movement['kind'],
    qtyDelta: String(row.qty_delta),
    unitCost: textValue(row.unit_cost),
    cogsAmount: textValue(row.cogs_amount),
    pendingCost: Boolean(row.pending_cost),
    holderRef: textValue(row.holder_ref),
    transferGroup: textValue(row.transfer_group),
    occurredAt: new Date(String(row.occurred_at)),
    createdAt: new Date(String(row.created_at)),
  }
}

type QueryHandle = Database<InventorySchema> | Transaction<InventorySchema>
type TxCapable = QueryHandle & {
  transaction?: <T>(fn: (tx: Transaction<InventorySchema>) => Promise<T>) => Promise<T>
}

export async function withInventoryTransaction<T>(
  db: QueryHandle,
  fn: (tx: Transaction<InventorySchema>) => Promise<T>,
): Promise<T> {
  const candidate = db as TxCapable
  if (typeof candidate.transaction === 'function') {
    return candidate.transaction(fn)
  }
  throw new InventoryTransactionRequiredError()
}
