import type { SQL } from 'drizzle-orm'
import type { PgColumn, PgTable } from 'drizzle-orm/pg-core'
import type { Querier, Schema } from '@platform-modules/db'

export type LedgerRef = Record<string, unknown> | null

export type AppendEntryInput = {
  key: string
  delta: bigint
  currency?: string | null
  reason: string
  ref?: LedgerRef
}

export type AppendEntryResult = {
  inserted: boolean
  /** The inserted entry's uuid; null when the key already existed (onConflictDoNothing returned no row). */
  id: string | null
}

/** Default module-owned wallet projection (optional — host may ignore). */
export type WalletBalanceTarget = {
  kind: 'wallet'
  ownerId: string
}

/** Host-owned balance column folded onto an existing domain row (column-balance pattern). */
export type ColumnBalanceTarget = {
  kind: 'column'
  table: PgTable
  where: SQL
  balanceColumn: PgColumn
}

export type BalanceTarget = WalletBalanceTarget | ColumnBalanceTarget

export type DebitInput = {
  key: string
  target: BalanceTarget
  amount: bigint
  reason: string
  ref?: LedgerRef
}

export type DebitResult = {
  inserted: boolean
  balance: bigint
}

export type DebitWithReadLock = {
  table: PgTable
  where: SQL
}

export type DebitWithReadInput = {
  key: string
  reason: string
  ref?: LedgerRef
  lock: DebitWithReadLock
}

export type DebitWithReadPlan<S extends Schema = Record<string, never>> = {
  delta: bigint
  apply: (tx: Querier<S>) => Promise<void>
}

export type DebitWithReadFn<S extends Schema, TRow extends Record<string, unknown>> = (
  rows: TRow[],
) => DebitWithReadPlan<S> | Promise<DebitWithReadPlan<S>>

export type DebitWithReadResult = {
  inserted: boolean
  /** The inserted entry's uuid; null when the key already existed. */
  id: string | null
}

export type LedgerEntry = {
  id: string
  delta: bigint
  currency: string | null
  reason: string
  ref: LedgerRef
  idempotencyKey: string
  createdAt: Date
}
