import type { Resource } from './resource.js';

// The per-port `outputs` record on the compose compile response, keyed
// `<nodeId>.<portName>`. One entry exists for every linear resource output
// port in the flow, whether a later node spends it (`consumed`) or it is
// delivered to `owner` (`terminal`). An entry is omitted only when its port
// declares `omitIfZero` and the simulation measured it at zero. `estimate` is
// the measured value when the simulation observed the port, otherwise the
// prepared op's quote, otherwise absent. `minimum` is the enforced floor: the
// larger of a guard floor and an op floor when either exists (tagged with its
// source, `guard` on a tie), else the estimate echoed when the port declares
// `providesMinimum` (`declared`), else absent. There is no zero placeholder;
// an absent `minimum` means no floor is known.

export type EstimateBasis = 'simulated' | 'quoted';

export type MinimumBasis = 'guard' | 'op' | 'declared';

export interface Estimate {
  readonly basis: EstimateBasis;
  readonly value: bigint;
}

export interface Minimum {
  readonly basis: MinimumBasis;
  readonly value: bigint;
}

export interface Amount {
  readonly estimate?: Estimate;
  readonly minimum?: Minimum;
}

// `etaSeconds` is the routing edge's or prepared quote's published estimate of
// how long deferred proceeds take to land; absent means no estimate is
// published, never zero. `provider` is the key of the external system that
// delivers them — for `lifi.bridge` the LI.FI tool key, which is the `bridge`
// parameter of LI.FI's `/v1/status` lookup; absent when the op does not name
// one.
export type Delivery =
  | { readonly when: 'now' }
  | {
      readonly when: 'future';
      readonly etaSeconds?: number;
      readonly provider?: string;
    };

interface OutputBase {
  readonly resource: Resource;
  readonly amount: Amount;
}

export interface ConsumedOutput extends OutputBase {
  readonly role: 'consumed';
  // The id of the call whose non-copy input binds this port.
  readonly consumedBy: string;
}

export interface TerminalOutput extends OutputBase {
  readonly role: 'terminal';
  readonly owner: string;
  readonly delivery: Delivery;
}

export type Output = ConsumedOutput | TerminalOutput;

export type Outputs = Record<string, Output>;
