/**
 * Same-transaction activity writer helpers — activity-timeline (wave-12).
 *
 * Each helper accepts a Drizzle transaction handle (DbTx) so the caller
 * controls atomicity. These helpers NEVER open their own transaction.
 *
 * Usage (inside a db.transaction callback):
 *   return db.transaction(async (tx) => {
 *     const [row] = await tx.insert(invoices).values(...).returning()
 *     await appendInvoiceActivity(tx, { tenantId, invoiceId: row.id, actorId, eventType: 'created' })
 *     return row
 *   })
 *
 * For system/automated events pass actorId: null, actorType: 'system'.
 */
import type { ActorType } from '@zync/types'
import type { DbTx } from '../client'
import {
  invoiceActivities,
  projectActivities,
  customerActivities,
  vendorActivities,
} from '../schema'

// ── Shared base ───────────────────────────────────────────────────────────────

interface AppendActivityBase {
  tenantId: string
  actorId: string | null
  actorType?: ActorType            // default 'user'
  eventType: string
  metadata?: Record<string, unknown>
  note?: string | null
}

// ── Invoice activity ──────────────────────────────────────────────────────────

export async function appendInvoiceActivity(
  tx: DbTx,
  args: AppendActivityBase & { invoiceId: string },
): Promise<{ id: string }> {
  const [row] = await tx
    .insert(invoiceActivities)
    .values({
      tenantId: args.tenantId,
      invoiceId: args.invoiceId,
      actorId: args.actorId,
      actorType: args.actorType ?? 'user',
      eventType: args.eventType,
      metadata: args.metadata ?? {},
      note: args.note ?? null,
    })
    .returning({ id: invoiceActivities.id })

  if (!row) throw new Error('Failed to write invoice activity')
  return row
}

// ── Project activity ──────────────────────────────────────────────────────────

export async function appendProjectActivity(
  tx: DbTx,
  args: AppendActivityBase & { projectId: string },
): Promise<{ id: string }> {
  const [row] = await tx
    .insert(projectActivities)
    .values({
      tenantId: args.tenantId,
      projectId: args.projectId,
      actorId: args.actorId,
      actorType: args.actorType ?? 'user',
      eventType: args.eventType,
      metadata: args.metadata ?? {},
      note: args.note ?? null,
    })
    .returning({ id: projectActivities.id })

  if (!row) throw new Error('Failed to write project activity')
  return row
}

// ── Customer activity ─────────────────────────────────────────────────────────

export async function appendCustomerActivity(
  tx: DbTx,
  args: AppendActivityBase & { customerId: string },
): Promise<{ id: string }> {
  const [row] = await tx
    .insert(customerActivities)
    .values({
      tenantId: args.tenantId,
      customerId: args.customerId,
      actorId: args.actorId,
      actorType: args.actorType ?? 'user',
      eventType: args.eventType,
      metadata: args.metadata ?? {},
      note: args.note ?? null,
    })
    .returning({ id: customerActivities.id })

  if (!row) throw new Error('Failed to write customer activity')
  return row
}

// ── Vendor activity ───────────────────────────────────────────────────────────

export async function appendVendorActivity(
  tx: DbTx,
  args: AppendActivityBase & { vendorId: string },
): Promise<{ id: string }> {
  const [row] = await tx
    .insert(vendorActivities)
    .values({
      tenantId: args.tenantId,
      vendorId: args.vendorId,
      actorId: args.actorId,
      actorType: args.actorType ?? 'user',
      eventType: args.eventType,
      metadata: args.metadata ?? {},
      note: args.note ?? null,
    })
    .returning({ id: vendorActivities.id })

  if (!row) throw new Error('Failed to write vendor activity')
  return row
}
