/**
 * W5 — Thin Stripe money-move adapter for module PayoutExecutor.
 * DB/status orchestration lives in @platform-modules/affiliate settlePayout.
 */
import type { PayoutExecutor } from '@platform-modules/affiliate';
import type Stripe from 'stripe';
import { asPayoutId, toModuleRef } from '@/server/platform-seams/ids.js';

export function createAffiliatePayoutExecutor(stripe: Stripe): PayoutExecutor {
  return {
    async execute({ payoutId, amountMinor, destination }) {
      const amount = Number(amountMinor);
      const payoutRef = toModuleRef(asPayoutId(payoutId));

      let transfer: Stripe.Transfer;
      try {
        transfer = await stripe.transfers.create(
          {
            amount,
            currency: 'ils',
            destination: destination.accountId,
            description: `Affiliate payout ${payoutRef}`,
          },
          { idempotencyKey: `affiliate-transfer-${payoutRef}` },
        );
      } catch (err: unknown) {
        const msg = err instanceof Error ? err.message : String(err);
        return { ok: false, code: 'TRANSFER_FAILED', error: msg };
      }

      // Donor-accepted residual: transfer may succeed then payout throws → PAYOUT_FAILED
      // while funds already left platform→Express (affiliate-payout.ts:134).
      let payout: Stripe.Payout;
      try {
        payout = await stripe.payouts.create(
          {
            amount,
            currency: 'ils',
            description: `Affiliate payout ${payoutRef}`,
          },
          {
            stripeAccount: destination.accountId,
            idempotencyKey: `affiliate-payout-${payoutRef}`,
          },
        );
      } catch (err: unknown) {
        const msg = err instanceof Error ? err.message : String(err);
        return { ok: false, code: 'PAYOUT_FAILED', error: msg };
      }

      return {
        ok: true,
        externalRefs: { transferId: transfer.id, payoutId: payout.id },
      };
    },
  };
}
