/**
 * Purchase domain events — discriminated union.
 *
 * Covers the paymentStatus state machine driven by workflows/purchase.ts:
 *   PENDING + charge_attempted(ok: true)  → COMPLETED
 *   PENDING + charge_attempted(ok: false) → DELETED
 *
 * The redemptionStatus transitions (UNREDEEMED → REDEEMED / EXPIRED / CANCELLED)
 * belong to the redemption aggregate and are NOT modelled here.
 *
 * Pure module: no imports from @/server/db, do-client, outbox-producer, payments, or fetch.
 */

// ─── Charge outcome ───────────────────────────────────────────────────────────

export type ChargeOutcome = { ok: true } | { ok: false; message: string };

// ─── Events ───────────────────────────────────────────────────────────────────

export type PurchaseEvent =
  /**
   * Fired after multiVendorCharge returns (registered or guest path).
   * The charge call itself stays in the orchestrator; the decider runs post-charge.
   */
  {
    kind: 'charge_attempted';
    outcome: ChargeOutcome;
    /** Plaintext guest email — present only on guest path, undefined for registered. */
    guestEmail?: string;
    /** Magic link URL — present only on guest path. */
    magicLinkUrl?: string;
    /** Guest confirmation URL with access token — present only on guest path. */
    confirmationUrl?: string;
    /** Whether to create a club membership (registered path only). */
    createClubMembership: boolean;
    /** Buyer user ID — present only on registered path. */
    userId?: string;
    /** Vendor ID (for push notification). */
    vendorId: string;
    /** Deal title (for push notification and outbox payloads). */
    dealTitle: string;
    /** Amount paid as decimal string. */
    amountPaid: string;
    /** Whether the buyer has an email on file (registered path). */
    hasBuyerEmail: boolean;
    at: Date;
  };
