export type GatewayJsonPrimitive = string | number | boolean | null;

export type GatewayJsonValue =
  | GatewayJsonPrimitive
  | GatewayJsonValue[]
  | GatewayJsonObject;

export type GatewayJsonObject = {
  [key: string]: GatewayJsonValue;
};

export type GatewayDigest = `sha256:${string}`;

export const GATEWAY_ADAPTER_VERSION: "3.0.0";
export const PAYEE_IDENTITY_PROFILE: "MANDATESHIELD_PAYEE_IDENTITY_V1";
export const LEGACY_EXECUTION_MODE: "LEGACY_DIRECT_CONSUME_V1";
export const SIGNED_EXECUTION_PERMIT_MODE: "SIGNED_EXECUTION_PERMIT_V1";

export type GatewayExecutionMode =
  | typeof LEGACY_EXECUTION_MODE
  | typeof SIGNED_EXECUTION_PERMIT_MODE;

export interface MandateShieldGatewayErrorOptions {
  cause?: unknown;
  code?: string;
  retryable?: boolean;
  details?: unknown;
}

export class MandateShieldGatewayError extends Error {
  constructor(
    message: string,
    options?: MandateShieldGatewayErrorOptions,
  );
  code: string;
  retryable: boolean;
  details: unknown | null;
}

export type GatewayPayeeProvider =
  | "X402"
  | "MPP"
  | "STRIPE"
  | "CUSTOM";

export type GatewayX402PayeeIdentity = GatewayJsonObject & {
  profile: typeof PAYEE_IDENTITY_PROFILE;
  provider: "X402";
  merchant_id: string;
  binding: GatewayJsonObject & {
    network: string;
    pay_to: string;
  };
  verification: GatewayJsonObject & {
    method: "TRUSTED_MERCHANT_MAPPING";
    verifier: string;
    evidence_ref: string;
  };
};

export type GatewayMppPayeeIdentity = GatewayJsonObject & {
  profile: typeof PAYEE_IDENTITY_PROFILE;
  provider: "MPP";
  merchant_id: string;
  binding: GatewayJsonObject & {
    service_origin: string;
    method: string;
  };
  verification: GatewayJsonObject & {
    method: "TLS_SERVICE_ORIGIN";
    verifier: string;
    evidence_ref: string;
  };
};

export type GatewayStripePayeeIdentity = GatewayJsonObject & {
  profile: typeof PAYEE_IDENTITY_PROFILE;
  provider: "STRIPE";
  merchant_id: string;
  binding: GatewayJsonObject & {
    connected_account_id: string;
    merchant_account_id: string;
  };
  verification: GatewayJsonObject & {
    method: "STRIPE_ACCOUNT_CONFIGURATION";
    verifier: string;
    evidence_ref: string;
  };
};

export type GatewayCustomPayeeIdentity = GatewayJsonObject & {
  profile: typeof PAYEE_IDENTITY_PROFILE;
  provider: "CUSTOM";
  merchant_id: string;
  binding: GatewayJsonObject & {
    service_origin: string;
    provider_id: string;
  };
  verification: GatewayJsonObject & {
    method: "HTTPS_WELL_KNOWN";
    verifier: string;
    evidence_ref: string;
  };
};

export type GatewayCanonicalPayeeIdentity =
  | GatewayX402PayeeIdentity
  | GatewayMppPayeeIdentity
  | GatewayStripePayeeIdentity
  | GatewayCustomPayeeIdentity;

export type GatewayFiatAmount = GatewayJsonObject & {
  minor_units: number;
  currency: string;
};

export type GatewayAtomicAmount = GatewayJsonObject & {
  atomic_units: string;
  asset_decimals: number;
};

export type GatewayFiatEnvelope = GatewayJsonObject & {
  merchant_id: string;
  payee_identity: GatewayCanonicalPayeeIdentity;
  amount: GatewayFiatAmount;
};

export type GatewayAtomicEnvelope = GatewayJsonObject & {
  merchant_id: string;
  payee_identity: GatewayCanonicalPayeeIdentity;
  amount: GatewayAtomicAmount;
  asset_id: string;
  network: string;
  resource: string;
};

export type GatewayEnvelope =
  | GatewayFiatEnvelope
  | GatewayAtomicEnvelope;

export type GatewayProviderPermitProfile =
  | "GENERIC_HTTP_V1"
  | "STRIPE_PAYMENT_INTENTS_V1"
  | "X402_V2_EXACT"
  | "MPP_CHARGE_V1";

export interface GatewayProviderBinding {
  profile: GatewayProviderPermitProfile;
  environment: "test" | "live";
  account: string;
  request_id: string;
  /**
   * Exact merchant_id or one canonical provider destination from the already
   * validated payee_identity (for example x402 pay_to or a Stripe account).
   */
  payee_destination: string;
  method: "GET" | "POST" | "PUT" | "PATCH";
  resource: string;
  body_digest: GatewayDigest;
}

export interface GatewayPermitProviderBinding {
  profile: GatewayProviderPermitProfile;
  environment: "test" | "live";
  account: string;
  request_id: string;
  request_digest: GatewayDigest;
  idempotency_key: string;
}

export interface GatewayPermitPayeeBinding {
  merchant_id: string;
  destination: string;
  destination_digest: GatewayDigest;
}

export type GatewayPermitAmount =
  | {
      mode: "ISO_4217";
      minor_units: number;
      currency: string;
    }
  | {
      mode: "ATOMIC_ASSET";
      atomic_units: string;
      asset_decimals: number;
      asset_id: string;
      network: string;
    };

export interface GatewayPermitResourceBinding {
  method: "GET" | "POST" | "PUT" | "PATCH";
  uri: string;
  body_digest: GatewayDigest;
}

export interface GatewayPermitExpectedRequest {
  provider: GatewayPermitProviderBinding;
  payee: GatewayPermitPayeeBinding;
  amount: GatewayPermitAmount;
  resource: GatewayPermitResourceBinding;
}

export interface GatewayExecutionPermit {
  format: "application/mandateshield-execution-permit+jwt";
  compact: string;
  permit_id: `msp_${string}`;
  key_id: string;
  jwks_uri: "https://mandateshield.com/.well-known/jwks.json";
  verify_uri: "https://mandateshield.com/api/v2/execution-permits/verify";
  redemption_uri: "https://mandateshield.com/api/v2/execution-permits/redeem";
  expires_at: number;
  online_redemption_required: true;
  offline_one_use_enforced: false;
}

export interface GatewayExecutionReceipt extends GatewayJsonObject {
  format: "application/mandateshield-execution-receipt+jwt";
  compact: string;
  execution_receipt_id: `mse_${string}`;
  key_id: string;
  jwks_uri: "https://mandateshield.com/.well-known/jwks.json";
  verify_uri: "https://mandateshield.com/api/v2/execution-receipts/verify";
  historical_evidence_only: true;
  execution_authorized: false;
  evidence_class:
    | "FACILITATOR_SIGNED"
    | "PROVIDER_API_VERIFIED"
    | "CHAIN_FINALIZED";
  independent_verification: true;
}

export function validateCanonicalPayeeIdentity<
  Provider extends GatewayPayeeProvider,
>(
  value: unknown,
  envelopeMerchantId: string,
  expectedProvider: Provider,
  providerName: string,
): Extract<GatewayCanonicalPayeeIdentity, { provider: Provider }>;

export interface GatewayKeyInput<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  receipt_id: string;
  compact: string;
  expected_envelope: Envelope;
  expected_audience: string;
  provider_input?: ProviderInput;
}

export interface GatewayDerivedKeys {
  readonly journal_id: string;
  readonly binding_digest: GatewayDigest;
  readonly provider_input_digest?: GatewayDigest;
  readonly consume_idempotency_key: string;
  readonly commit_idempotency_key: string;
  readonly release_idempotency_key: string;
  readonly provider_create_idempotency_key: string;
  readonly provider_confirm_idempotency_key: string;
  readonly permit_redemption_idempotency_key: string;
}

export function deriveGatewayKeys<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
>(
  input: GatewayKeyInput<ProviderInput, Envelope>,
): Promise<Readonly<GatewayDerivedKeys>>;

export type GatewayJournalState =
  | "AWAITING_CONSUME"
  | "CONSUME_INTENT"
  | "CONSUMED"
  | "PROVIDER_INTENT"
  | "PROVIDER_PENDING"
  | "OUTCOME_UNKNOWN"
  | "RECONCILE_INTENT"
  | "FINALIZING_COMMIT"
  | "FINALIZING_RELEASE"
  | "COMMITTED"
  | "RELEASED"
  | "CONSUME_REJECTED"
  | "SUBMISSION_WINDOW_CLOSED";

export type GatewayProviderOutcome =
  | "COMMITTED"
  | "FAILED"
  | "NOT_SUBMITTED"
  | "PENDING"
  | "UNKNOWN";

export interface GatewayJournalRecord {
  id: string;
  version: number;
  state: GatewayJournalState;
  binding_digest: GatewayDigest;
  receipt_id: string;
  expected_audience: string;
  consume_idempotency_key: string;
  commit_idempotency_key: string;
  release_idempotency_key: string;
  provider_create_idempotency_key: string;
  provider_confirm_idempotency_key: string;
  provider_input_digest?: GatewayDigest;
  execution_mode?: typeof SIGNED_EXECUTION_PERMIT_MODE;
  provider_binding?: GatewayProviderBinding;
  provider_binding_digest?: GatewayDigest;
  permit_redemption_idempotency_key?: string;
  execution_permit?: GatewayExecutionPermit;
  execution_permit_digest?: GatewayDigest;
  permit_expected_request?: GatewayPermitExpectedRequest;
  permit_claim_id?: `mspc_${string}`;
  provider_submission_id?: `psub_${string}`;
  permit_redeemed_at?: string;
  consume_claimed_at?: string;
  consume_recovered_at?: string;
  consume_transitioned_at?: string;
  settlement_deadline_at?: number;
  provider_claimed_at?: string;
  reconcile_claimed_at?: string;
  reconcile_origin_state?: "PROVIDER_PENDING" | "OUTCOME_UNKNOWN";
  provider_intent_abandoned_at?: string;
  provider_reference?: string;
  provider_outcome?: GatewayProviderOutcome;
  provider_occurred_at?: string;
  provider_submission_fenced?: true;
  provider_submission_locked_at?: string;
  provider_evidence_id?: `pevd_${string}`;
  provider_evidence_class?:
    | "FACILITATOR_SIGNED"
    | "PROVIDER_API_VERIFIED"
    | "CHAIN_FINALIZED";
  provider_independent_verification?: true;
  execution_receipt?: GatewayExecutionReceipt;
  created_at: string;
  updated_at: string;
}

export interface GatewayJournalBeginResult {
  created: boolean;
  record: GatewayJournalRecord;
}

export interface GatewayJournalCompareAndSetInput {
  id: string;
  expected_version: number;
  expected_state: GatewayJournalState;
  record: GatewayJournalRecord;
}

/**
 * Customer-provided storage contract. The callbacks are required to provide
 * durable atomic insert/read and compare-and-set behavior; the declaration
 * does not establish that a particular implementation has those properties.
 */
export interface DurableGatewayJournal {
  readonly durable: true;
  /**
   * A customer declaration that every executor uses one globally shared,
   * linearizable namespace. Omission fails closed. The declaration is not an
   * independent storage attestation; split-brain deployments remain unsafe.
   */
  readonly consistency: "GLOBAL_SHARED_LINEARIZABLE";
  begin(record: GatewayJournalRecord): Promise<GatewayJournalBeginResult>;
  get(id: string): Promise<GatewayJournalRecord | null>;
  compareAndSet(
    input: GatewayJournalCompareAndSetInput,
  ): Promise<GatewayJournalRecord | null>;
}

export type GatewayCommittedOrPendingProviderResult = {
  outcome: "COMMITTED" | "PENDING";
  reference: string;
  occurred_at: string;
  reason?: string;
  submission_fenced?: never;
};

export type GatewayFailedProviderResult = {
  outcome: "FAILED" | "NOT_SUBMITTED";
  reference: string;
  occurred_at: string;
  reason?: string;
  submission_fenced?: true;
};

export type GatewayUnknownProviderResult = {
  outcome: "UNKNOWN";
  reference?: string;
  occurred_at: string;
  reason?: string;
  submission_fenced?: never;
};

export type GatewayProviderResult =
  | GatewayCommittedOrPendingProviderResult
  | GatewayFailedProviderResult
  | GatewayUnknownProviderResult;

export interface GatewayProviderBindingContext<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  receipt_id: string;
  envelope: Envelope;
  expected_audience: string;
  create_idempotency_key: string;
  confirm_idempotency_key: string;
  provider_input?: ProviderInput;
  execution_mode?: GatewayExecutionMode;
  provider_binding?: GatewayProviderBinding;
}

export interface GatewayProviderExecutionContext<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> extends GatewayProviderBindingContext<ProviderInput, Envelope> {
  settlement_deadline_at: number;
  recovery_started_at: string;
  provider_reference?: string;
  execution_mode: GatewayExecutionMode;
  provider_submission_permitted: boolean;
  execution_permit?: GatewayExecutionPermit;
  provider_idempotency_key?: string;
  permit_claim_id?: `mspc_${string}`;
  provider_submission_id?: `psub_${string}`;
}

export interface LegacyCustomerSidePaymentProvider<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  readonly name: string;
  readonly payeeIdentityProvider: GatewayPayeeProvider;
  readonly executionMode?: typeof LEGACY_EXECUTION_MODE;
  readonly createProviderBinding?: never;
  readonly referenceFreeReconcileAfterDeadline?: boolean;
  validateBinding(
    context: GatewayProviderBindingContext<ProviderInput, Envelope>,
  ): void | Promise<void>;
  submit(
    context: GatewayProviderExecutionContext<ProviderInput, Envelope>,
  ): Promise<GatewayProviderResult>;
  reconcile(
    context: GatewayProviderExecutionContext<ProviderInput, Envelope>,
  ): Promise<GatewayProviderResult>;
}

export interface SignedPermitCustomerSidePaymentProvider<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  readonly name: string;
  readonly payeeIdentityProvider: GatewayPayeeProvider;
  readonly executionMode: typeof SIGNED_EXECUTION_PERMIT_MODE;
  readonly referenceFreeReconcileAfterDeadline?: boolean;
  createProviderBinding(
    context: GatewayProviderBindingContext<ProviderInput, Envelope>,
  ): GatewayProviderBinding | Promise<GatewayProviderBinding>;
  validateBinding(
    context: GatewayProviderBindingContext<ProviderInput, Envelope> & {
      execution_mode: typeof SIGNED_EXECUTION_PERMIT_MODE;
      provider_binding: GatewayProviderBinding;
    },
  ): void | Promise<void>;
  submit(
    context: GatewayProviderExecutionContext<ProviderInput, Envelope> & {
      execution_mode: typeof SIGNED_EXECUTION_PERMIT_MODE;
      provider_submission_permitted: true;
      provider_binding: GatewayProviderBinding;
      execution_permit: GatewayExecutionPermit;
      provider_idempotency_key: string;
      permit_claim_id: `mspc_${string}`;
      provider_submission_id: `psub_${string}`;
    },
  ): Promise<GatewayProviderResult>;
  reconcile(
    context: GatewayProviderExecutionContext<ProviderInput, Envelope> & {
      execution_mode: typeof SIGNED_EXECUTION_PERMIT_MODE;
      provider_submission_permitted: false;
      provider_binding: GatewayProviderBinding;
      execution_permit: GatewayExecutionPermit;
      provider_submission_id: `psub_${string}`;
    },
  ): Promise<GatewayProviderResult>;
}

export type CustomerSidePaymentProvider<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> =
  | LegacyCustomerSidePaymentProvider<ProviderInput, Envelope>
  | SignedPermitCustomerSidePaymentProvider<
      ProviderInput,
      Envelope
    >;

export type GatewayProcessorAmount =
  | {
      minor_units: number;
      currency: string;
    }
  | {
      atomic_units: string;
      asset_decimals: number;
      asset_id: string;
      network: string;
      resource: string;
    };

export interface GatewayProcessorResult<
  Outcome extends
    | "COMMITTED"
    | "FAILED"
    | "NOT_SUBMITTED" =
    | "COMMITTED"
    | "FAILED"
    | "NOT_SUBMITTED",
> {
  payment_reference: string;
  outcome: Outcome;
  payee: string;
  audience: string;
  occurred_at: string;
  amount: GatewayProcessorAmount;
}

export interface GatewayTransitionBase<
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  receipt_id: string;
  compact: string;
  idempotency_key: string;
  expected_envelope: Envelope;
  expected_audience: string;
}

export type GatewayConsumeTransitionInput<
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> = GatewayTransitionBase<Envelope> & {
  action: "CONSUME";
  provider_binding?: GatewayProviderBinding;
  processor_result?: never;
};

export type GatewayTerminalTransitionInput<
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> =
  | (GatewayTransitionBase<Envelope> & {
      action: "COMMIT";
      processor_result: GatewayProcessorResult<"COMMITTED">;
      provider_evidence_id?: never;
    })
  | (GatewayTransitionBase<Envelope> & {
      action: "RELEASE";
      processor_result: GatewayProcessorResult<
        "FAILED" | "NOT_SUBMITTED"
      >;
      provider_evidence_id?: never;
    })
  | (GatewayTransitionBase<Envelope> & {
      action: "COMMIT" | "RELEASE";
      provider_evidence_id: `pevd_${string}`;
      processor_result?: never;
    });

export type GatewayTransitionInput<
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> =
  | GatewayConsumeTransitionInput<Envelope>
  | GatewayTerminalTransitionInput<Envelope>;

export interface GatewayTransitionClientOptions {
  acceptIdempotentConsumeReplay?: boolean;
}

export type GatewayLegacyConsumeTransitionResponse =
  GatewayJsonObject & {
    receipt_id: string;
    action: "CONSUME";
    transition_state: "CONSUMED";
    current_state: "CONSUMED";
    transitioned_at: number;
    expires_at: number;
    settlement_deadline_at: number;
    processor_result_recorded: false;
    processor_audience: string;
    payment_reference: null;
    processor_integration_required: true;
  } & (
    | {
        idempotent_replay: false;
        provider_submission_permitted: true;
      }
    | {
        idempotent_replay: true;
        provider_submission_permitted: false;
      }
  );

export type GatewaySignedPermitConsumeTransitionResponse =
  GatewayJsonObject & {
    receipt_id: string;
    action: "CONSUME";
    transition_state: "CONSUMED";
    current_state: "CONSUMED";
    transitioned_at: number;
    expires_at: number;
    settlement_deadline_at: number;
    idempotent_replay: boolean;
    processor_result_recorded: false;
    processor_audience: string;
    payment_reference: null;
    processor_integration_required: true;
    provider_submission_permitted: false;
    provider_redemption_required: true;
    execution_permit: GatewayExecutionPermit;
  };

export type GatewayConsumeTransitionResponse =
  | GatewayLegacyConsumeTransitionResponse
  | GatewaySignedPermitConsumeTransitionResponse;

export type GatewayCommitTransitionResponse = GatewayJsonObject & {
  receipt_id: string;
  action: "COMMIT";
  transition_state: "COMMITTED";
  current_state: "COMMITTED";
  transitioned_at: number;
  expires_at: number;
  settlement_deadline_at: number;
  idempotent_replay: boolean;
  processor_result_recorded: true;
  processor_audience: string;
  payment_reference: string;
  processor_integration_required: true;
  provider_submission_permitted: false;
  independent_verification?: boolean;
  provider_evidence_id?: `pevd_${string}` | null;
  evidence_class?: string | null;
  execution_receipt?: GatewayExecutionReceipt | null;
};

export type GatewayReleaseTransitionResponse = GatewayJsonObject & {
  receipt_id: string;
  action: "RELEASE";
  transition_state: "RELEASED";
  current_state: "RELEASED";
  transitioned_at: number;
  expires_at: number;
  settlement_deadline_at: number;
  idempotent_replay: boolean;
  processor_result_recorded: true;
  processor_audience: string;
  payment_reference: string;
  processor_integration_required: true;
  provider_submission_permitted: false;
  independent_verification?: boolean;
  provider_evidence_id?: `pevd_${string}` | null;
  evidence_class?: string | null;
  execution_receipt?: GatewayExecutionReceipt | null;
};

export type GatewayTransitionResponse =
  | GatewayConsumeTransitionResponse
  | GatewayCommitTransitionResponse
  | GatewayReleaseTransitionResponse;

export interface GatewayPermitRedemptionInput {
  permit_id: `msp_${string}`;
  compact: string;
  idempotency_key: string;
  expected_audience: string;
  expected_request: GatewayPermitExpectedRequest;
}

export interface GatewayFreshPermitRedemption {
  active: true;
  status: "CLAIMED";
  permit_id: `msp_${string}`;
  claim_id: `mspc_${string}`;
  provider_submission_id: `psub_${string}`;
  claimed_at: number;
  idempotent_replay: false;
  same_claim: true;
  credential_bound: true;
  provider_submission_permitted: true;
  provider_idempotency_key: string;
  bindings: {
    audience: string;
    provider: GatewayPermitProviderBinding;
    payee: GatewayPermitPayeeBinding;
    amount: GatewayPermitAmount;
    resource: GatewayPermitResourceBinding;
  };
}

export interface GatewayProviderSubmissionReportInput {
  provider_submission_id: `psub_${string}`;
  permit_id: `msp_${string}`;
  claim_id: `mspc_${string}`;
  payment_reference: string;
  outcome: "COMMITTED" | "FAILED" | "PENDING" | "UNKNOWN";
  occurred_at: string;
  provider_observation: GatewayJsonObject;
}

export type GatewayProviderSubmissionReportResponse =
  GatewayJsonObject & {
    provider_submission_id: `psub_${string}`;
    permit_id: `msp_${string}`;
    state:
      | "SETTLED"
      | "FAILED_CONFIRMED"
      | "UNKNOWN"
      | "CONFLICT"
      | "PENDING";
    payment_reference: string;
    caller_evidence_recorded: true;
    independent_verification: boolean;
    evidence_class:
      | "FACILITATOR_SIGNED"
      | "PROVIDER_API_VERIFIED"
      | "CHAIN_FINALIZED"
      | "UNRESOLVED";
    evidence_id: `pevd_${string}`;
    outcome: "COMMITTED" | "FAILED_CONFIRMED" | "UNKNOWN";
    terminal_transition_permitted: boolean;
    reconciliation_required: boolean;
    idempotent_replay: boolean;
    authorization_finalized: boolean;
    final_authorization_state: "COMMITTED" | "RELEASED" | null;
    execution_receipt: GatewayExecutionReceipt | null;
  };

export interface MandateShieldProcessorClient<
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  transitionExecutionAuthorization(
    input: GatewayTransitionInput<Envelope>,
    options?: GatewayTransitionClientOptions,
  ): Promise<GatewayTransitionResponse>;
  redeemExecutionPermit?(
    input: GatewayPermitRedemptionInput,
  ): Promise<GatewayFreshPermitRedemption>;
  reportProviderSubmission?(
    input: GatewayProviderSubmissionReportInput,
  ): Promise<GatewayProviderSubmissionReportResponse>;
}

export type GatewayExecutionInput<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> = GatewayKeyInput<ProviderInput, Envelope>;

export interface GatewayExecutionResult {
  readonly journal_id: string;
  readonly receipt_id: string;
  readonly state: GatewayJournalState;
  readonly outcome: GatewayProviderOutcome;
  readonly terminal: boolean;
  readonly replay: boolean;
  readonly execution_mode: GatewayExecutionMode;
  readonly provider_reference?: string;
}

export interface MandateShieldGatewayOptions<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  journal: DurableGatewayJournal;
  mandateShield: MandateShieldProcessorClient<Envelope>;
  provider: CustomerSidePaymentProvider<ProviderInput, Envelope>;
  clock?: () => number;
  providerIntentLeaseMs?: number;
  consumeIntentLeaseMs?: number;
  reconcileIntentLeaseMs?: number;
}

export interface MandateShieldGateway<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
> {
  readonly version: typeof GATEWAY_ADAPTER_VERSION;
  readonly provider: string;
  readonly executionMode: GatewayExecutionMode;
  readonly legacy: boolean;
  execute(
    input: GatewayExecutionInput<ProviderInput, Envelope>,
  ): Promise<Readonly<GatewayExecutionResult>>;
}

export function createMandateShieldGateway<
  ProviderInput extends GatewayJsonValue = GatewayJsonValue,
  Envelope extends GatewayEnvelope = GatewayEnvelope,
>(
  options: MandateShieldGatewayOptions<ProviderInput, Envelope>,
): MandateShieldGateway<ProviderInput, Envelope>;
