/**
 * Purchase domain effects — discriminated union.
 *
 * The machine emits effects; apply-effects.ts interprets them.
 * Pure module: no imports from @/server/db, do-client, outbox-producer, payments, or fetch.
 *
 * Effect ordering in apply-effects.ts (canonical):
 *   1. complete-payment (DB update purchases + deals + users)
 *   2. enqueue-outbox (DB insert + queue send, per effect)
 *   3. send-vendor-push (non-critical external I/O, best-effort)
 *   4. delete-pending (on charge failure — DB delete)
 */

export type PurchaseEffect =
  /** Mark purchase COMPLETED, update qrTokenHash + qrPngUrl, increment quantitySold + purchaseCount. */
  | {
      kind: 'complete-payment';
      purchaseId: string;
      dealId: string;
      /** Defined only on registered path. */
      userId?: string;
      finalQrTokenHash: string;
      qrPngUrl: string;
    }
  /** Delete the orphan PENDING purchase row on charge failure. */
  | {
      kind: 'delete-pending';
      purchaseId: string;
    }
  /** Insert outbox row + enqueue (one effect per event). */
  | {
      kind: 'enqueue-outbox';
      eventType: string;
      aggregateType: string;
      aggregateId: string;
      payload: Record<string, unknown>;
    }
  /** Notify vendor of new sale (best-effort, non-blocking). */
  | {
      kind: 'send-vendor-push';
      vendorId: string;
      dealTitle: string;
      amountPaid: string;
      purchaseId: string;
    }
  /** Check if deal is sold out and update dealState accordingly. */
  | {
      kind: 'check-sold-out';
      dealId: string;
    };
