/**
 * Canonical request types for the `POST /compose/route` convenience endpoint.
 * Amounts accept `bigint | string` for authoring convenience; the JSON wire
 * format is always a decimal string, which the SDK serialises for you.
 *
 * `/compose/route` trades authoring power for brevity. Instead of a full flow
 * document it takes a single from/to token pair; the server builds a
 * `lifi.zap` flow with a `directDeposit` input on the caller's behalf and runs
 * it through the same compile pipeline as `POST /compose`. As of today the flow
 * it builds is a single zap step — one edge of the server's routing catalog —
 * and it is meant to author richer flows later, which this request shape is
 * deliberately agnostic about. Its response body is byte-identical to that of
 * `POST /compose` — the enveloped `ComposeCompileSuccessData` on HTTP 200 and
 * `ComposeCompilePartialData` on HTTP 206 — so this file declares only the
 * request shape and reuses `ComposeCompileResult` from `./compile.js` for the
 * result.
 *
 * These are the single source of truth for the request shape, hand-authored
 * here for the same reason as `./compile.ts` and `./simulate.ts` rather than
 * derived from the validating schema: that schema is the Zod one in
 * `@lifi/api-schemas` (`src/routes/composeRoute.ts`), a package that depends on
 * this one, so importing its inferred types here would invert the dependency —
 * and the public SDK ships this package as its only peer dependency, never the
 * server's schema package. The two definitions are held in lockstep by a
 * compile-time conformance assertion
 * (`api-schemas/src/routes/composeRoute.typecheck.ts`), which fails the build
 * if either side drifts.
 */

import type { SimulationPolicy, SweepTo } from './compile.js';

/**
 * Spend an exact amount of `fromToken`.
 *
 * `amount` is in the token's smallest unit. Accepts `bigint | string`; the wire
 * format is a non-negative decimal string.
 */
export interface RouteAmountExact {
  readonly type: 'EXACT';
  readonly amount: bigint | string;
}

/**
 * Spend the signer's entire `fromToken` balance, whatever it is at execution
 * time.
 *
 * The on-chain amount is resolved by a deposit-all materialiser, so it is not
 * known when the route is compiled. `simAmount` is the stand-in the server
 * quotes and simulates against — make it a realistic estimate of the balance,
 * because it determines the quote and the derived preconditions, not the amount
 * actually moved. Accepts `bigint | string`; the wire format is a non-negative
 * decimal string.
 *
 * Not supported when `fromToken` is the chain's native sentinel: a gas coin
 * arrives via `msg.value`, so there is no on-chain balance to sweep, and the
 * server rejects the combination with a `validation_error`. Use
 * {@link RouteAmountExact} for native inputs.
 */
export interface RouteAmountAll {
  readonly type: 'ALL';
  readonly simAmount: bigint | string;
}

/**
 * How much of `fromToken` a route spends. Two variants, discriminated by
 * `type`.
 */
export type RouteAmount = RouteAmountExact | RouteAmountAll;

/** Request body for `POST /compose/route`. */
export interface ComposeRouteRequest {
  /** EVM chain id. Both tokens must live on this chain — routes are same-chain. */
  readonly chainId: number;
  /**
   * Token to spend. Use the chain's native sentinel address for the gas coin
   * (the zero address on EVM-native chains).
   */
  readonly fromToken: string;
  /** Token to receive. */
  readonly toToken: string;
  /** How much of `fromToken` to spend — an exact amount or the whole balance. */
  readonly amount: RouteAmount;
  /** Address that funds the route and, by default, owns its output. */
  readonly signer: string;
  /**
   * Slippage tolerance in basis points, applied as a guard on the route's
   * output. Range 0–10000. Defaults to `100` (1%) server-side when omitted.
   */
  readonly slippageBps?: number;
  /**
   * Reject the route when its quoted price impact exceeds this many basis
   * points. Range 0–10000. Omitted ⇒ no price-impact guard is installed.
   */
  readonly maxPriceImpactBps?: number;
  /**
   * Integrator fee in basis points, taken from the input amount. Range 0–9000.
   * Defaults to `0` server-side when omitted. A non-zero value requires an
   * integration-scoped API key; the server rejects it otherwise.
   */
  readonly integratorFeeBps?: number;
  /** Opaque referrer tag forwarded to the underlying quote provider. */
  readonly referrer?: string;
  /**
   * Owner of the route's output; defaults to `signer`. Routes whose protocol
   * mints to a named receiver (surfaced as `recipient: 'required'` by
   * `GET /compose/zap-packs`) bind this address at mint time rather than
   * transferring afterwards. Accepts an address or `{ $ref: 'context.sender' }`;
   * `{ $ref: 'context.executionAddress' }` is rejected.
   */
  readonly sweepTo?: SweepTo;
  /**
   * `'strict'` (the default) fails the request when simulation detects a
   * revert; `'allow-revert'` returns a partial result with revert diagnostics
   * instead.
   */
  readonly simulationPolicy?: SimulationPolicy;
  /**
   * Also simulate the final user-facing transaction after the structured
   * simulation succeeds. Reverts honour `simulationPolicy`. Defaults to `false`.
   */
  readonly simulateUserProgram?: boolean;
  /**
   * Filter the returned `approvals` against current on-chain allowances,
   * omitting approvals that are already sufficient. Defaults to `false`.
   */
  readonly checkOnChainAllowances?: boolean;
}
