import type { VerificationDescriptor } from './descriptor.js';
import type { InputSpec, Precondition } from './flow.js';
import type { Flow } from './flowSchema.js';
import type { ProducedResource } from './resource.js';
import type { ContinuationPlanWire, Phase1ArtifactWire } from './zodSchemas.js';

export type SimulationPolicy = 'strict' | 'allow-revert';

/**
 * Destination for sweeping proxy-held terminal resources after execution.
 * Either a literal EVM address or a `{ $ref }` context reference
 * (e.g. `{ $ref: "context.sender" }`).
 */
export type SweepTo = string | { readonly $ref: string };

export interface ComposeRun {
  readonly inputs: Record<string, InputSpec>;
  readonly preconditions?: readonly Precondition[];
  readonly signer: string;
  readonly assumptions?: Record<string, bigint>;
  readonly referrer?: string;
  readonly integratorFeeBps?: number;
  readonly maxPriceImpactBps?: number;
  readonly sweepTo?: SweepTo;
  readonly simulationPolicy?: SimulationPolicy;
  readonly checkOnChainAllowances?: boolean;
}

export interface ComposeCompileRequest {
  readonly flow: Flow;
  readonly run: ComposeRun;
}

export interface PriceImpact {
  readonly inputValueUsd: number;
  readonly outputValueUsd: number;
  readonly impactBps: number;
  readonly unpricedInputs: readonly string[];
  readonly unpricedOutputs: readonly string[];
}

export interface ApprovalEntry {
  readonly token: string;
  readonly spender: string;
  readonly amount: string;
  readonly transactionRequest: {
    readonly to: string;
    readonly data: string;
    readonly value: '0';
  };
}

export interface SimulationRevert {
  readonly code: number;
  readonly rawErrorBytes: string;
  readonly decodeResult?: {
    readonly errorCandidates?: readonly {
      readonly decodedErrorSignature: string;
      readonly decodedParams: readonly string[];
    }[];
    readonly error?: string;
  };
}

export interface ComposeTransactionRequest {
  readonly to: string;
  readonly data: string;
  readonly value: string;
  readonly gasLimit?: string;
}

// A single continuation pointer: the node whose `future` output is awaited and
// the downstream flow that consumes its proceeds. A flow can declare several,
// carried in the response as `continuations`.
export interface ComposeContinuation {
  readonly awaits: string;
  readonly flowId: string;
}

// Continuation fields shared by the success and partial-error responses, so the
// two shapes cannot drift. `phase1ByNode` / `continuationPlans` reuse the
// Zod-inferred wire types from `zodSchemas.ts`, pinning these SDK-facing types
// to the server contract rather than hand-transcribing them.
interface ComposeContinuationData {
  // One pointer per `continuation.settle` branch (a flow can fork into several).
  readonly continuations?: readonly ComposeContinuation[];
  // Phase-1 action to sign/fund now, keyed by settle node. Absent for an atomic flow.
  readonly phase1ByNode?: Record<string, Phase1ArtifactWire>;
  // Self-serve second leg to re-submit later, keyed by settle node. Present only
  // for providers that hand the next leg back to the caller (manual-relay).
  readonly continuationPlans?: Record<string, ContinuationPlanWire>;
}

// One funding leg the compiled fill consumes: the resource input's token
// (native → zero address) and its statically resolved amount as a decimal
// string (verified continuations, plan GD-8, seam C5).
export interface SpendEntry {
  readonly token: string;
  readonly amount: string;
}

export interface ComposeCompileSuccessData extends ComposeContinuationData {
  readonly producedResources: Record<string, ProducedResource>;
  readonly transactionRequest: ComposeTransactionRequest;
  readonly userProxy: string;
  readonly priceImpact?: PriceImpact;
  readonly approvals?: readonly ApprovalEntry[];
  // GD-8 settlement-fill fields (seam C5), additive on every success response:
  // `spends` (the exact token amounts the fill consumes) and `quote.validUntilMs`
  // (fill freshness bound — earliest prepared-node `expiresAtMs`, else a
  // far-future sentinel).
  // `verificationDescriptor` (the echo) is present only when the flow carried a
  // `continuation.commitment` node.
  readonly spends?: readonly SpendEntry[];
  readonly quote?: { readonly validUntilMs: number };
  readonly verificationDescriptor?: VerificationDescriptor;
}

export interface ComposeCompilePartialData extends ComposeContinuationData {
  readonly producedResources: Record<string, ProducedResource>;
  readonly transactionRequest: ComposeTransactionRequest;
  readonly userProxy: string;
  readonly simulationRevert: SimulationRevert;
  readonly approvals?: readonly ApprovalEntry[];
}

export type ComposeCompileResult =
  | (ComposeCompileSuccessData & { readonly status: 'success' })
  | (ComposeCompilePartialData & {
      readonly status: 'partial';
      readonly error: { readonly kind: string; readonly message: string };
    });
