import type { InputSpec, Precondition } from "./flow.js";
import type { Flow } from "./flowSchema.js";
import type { ProducedResource } from "./resource.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;
}

export interface ComposeContinuation {
  readonly awaits: string;
  readonly flowId: string;
}

export interface ComposeCompileSuccessData {
  readonly producedResources: Record<string, ProducedResource>;
  readonly transactionRequest: ComposeTransactionRequest;
  readonly userProxy: string;
  readonly priceImpact?: PriceImpact;
  readonly approvals?: readonly ApprovalEntry[];
  readonly continuation?: ComposeContinuation;
}

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

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