/**
 * GroupReservation domain effects — discriminated union.
 *
 * The decider 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. mark-cancelled (DB update reservation.status)
 *   2. release-hold (best-effort provider release — no DB write)
 *   3. decrement-count (DB update group_deal counter)
 *   4. record-threshold-met / record-threshold-lost (delegate to group-deal workflow)
 *   5. promote-waitlist (DB update — pops next entry)
 *   6. enqueue-outbox (DB insert + queue send)
 *   7. send-push (non-idempotent external I/O, best-effort)
 */

export type GroupReservationEffect =
  /** Mark reservation row CANCELLED. */
  | {
      kind: 'mark-cancelled';
      reservationId: string;
    }
  /** Best-effort provider hold release (idempotent — Stripe PI cancel is idempotent). */
  | {
      kind: 'release-hold';
      reservationId: string;
      providerHoldId: string;
    }
  /** Decrement group_deal.currentReservationCount by N. */
  | {
      kind: 'decrement-count';
      groupDealId: string;
      quantity: number;
    }
  /** Delegate to group-deal workflow's recordThresholdMet (public API). */
  | {
      kind: 'record-threshold-met';
      groupDealId: string;
      dealId: string;
      vendorId: string;
      newCount: number;
    }
  /** Delegate to group-deal workflow's recordThresholdLost (public API). */
  | {
      kind: 'record-threshold-lost';
      groupDealId: string;
      dealId: string;
      vendorId: string;
      newCount: number;
      minGroupSize: number;
    }
  /** Pop the next waitlist entry (returns the promoted row from queries). */
  | {
      kind: 'promote-waitlist';
      groupDealId: string;
    }
  /** Insert outbox row + enqueue. */
  | {
      kind: 'enqueue-outbox';
      aggregateType: 'group_reservation' | 'group_deal';
      aggregateId: string;
      eventType: string;
      payload: Record<string, unknown>;
    }
  /** Push notification to user (best-effort). */
  | {
      kind: 'send-user-push';
      userId: string;
      title: string;
      body: string;
      url: string;
      tag: string;
      data: Record<string, unknown>;
    }
  /** Push notification to vendor (best-effort). */
  | {
      kind: 'send-vendor-push';
      vendorId: string;
      title: string;
      body: string;
      url: string;
      tag: string;
      data: Record<string, unknown>;
    };
