export type PlannerProvider =
  | 'dodo'
  | 'dodo_v3'
  | 'uniswap_v3'
  | 'uniswap_v2'
  | 'sushiswap'
  | 'balancer'
  | 'curve'
  | 'one_inch'
  | 'partner';
export type PlannerLegKind = 'swap' | 'bridge';
export type PlannerDecision = 'direct-pool' | 'multi-hop' | 'swap-bridge-swap' | 'bridge-only' | 'unresolved';
export type ComplianceProfile = 'standard' | 'institutional';

export interface PlannerConstraints {
  maxSlippageBps?: number;
  allowedProviders?: PlannerProvider[];
  maxLegs?: number;
  allowedIntermediates?: string[];
  complianceProfile?: ComplianceProfile;
  allowBridge?: boolean;
  preferredBridges?: string[];
  allowCommodityIntermediates?: boolean;
}

export interface PlannerRequest {
  sourceChainId: number;
  destinationChainId?: number;
  tokenIn: string;
  tokenOut: string;
  amountIn: string;
  recipient?: string;
  constraints?: PlannerConstraints;
}

export interface EncodedPlannerRouteLeg {
  provider: number;
  tokenIn: string;
  tokenOut: string;
  amountSource: number;
  minAmountOut: string;
  target: string;
  providerData: string;
}

export interface EncodedPlannerRoutePlan {
  chainId: number;
  inputToken: string;
  outputToken: string;
  amountIn: string;
  minAmountOut: string;
  recipient: string;
  deadline: string;
  legs: EncodedPlannerRouteLeg[];
}

export interface EncodedBridgeIntentPlan {
  sourcePlan: EncodedPlannerRoutePlan;
  bridgeType: string;
  bridgeData: string;
  destinationPlan: EncodedPlannerRoutePlan;
  recipient: string;
  deadline: string;
}

export interface PlannerLeg {
  kind: PlannerLegKind;
  provider: PlannerProvider;
  sourceChainId: number;
  destinationChainId: number;
  tokenInAddress: string;
  tokenOutAddress: string;
  tokenInSymbol?: string;
  tokenOutSymbol?: string;
  estimatedAmountIn: string;
  estimatedAmountOut: string;
  minAmountOut: string;
  target?: string;
  poolAddress?: string;
  providerData?: Record<string, unknown>;
  providerDataHex?: string;
  bridgeType?: string;
  bridgeAddress?: string;
  gasEstimate?: number;
  freshnessSeconds?: number | null;
  totalLiquidityUsd?: number;
  notes?: string[];
}

export interface PlannerAlternative {
  routeId: string;
  decision: PlannerDecision;
  estimatedAmountOut: string;
  estimatedGasUsd: number;
  providerPath: PlannerProvider[];
  legCount: number;
  score: number;
  notes: string[];
}

export interface PlannerStaleness {
  maxFreshnessSeconds: number | null;
  hasStaleLeg: boolean;
}

export interface PlannerResponse {
  planId: string;
  generatedAt: string;
  decision: PlannerDecision;
  sourceChainId: number;
  destinationChainId: number;
  tokenIn: string;
  tokenOut: string;
  estimatedAmountOut: string | null;
  minAmountOut: string | null;
  estimatedGasUsd: number;
  legs: PlannerLeg[];
  alternatives: PlannerAlternative[];
  confidenceScore: number;
  riskFlags: string[];
  selectedRouteReason: string;
  rejectedAlternatives: string[];
  staleness: PlannerStaleness;
  routePlan?: EncodedPlannerRoutePlan;
  bridgeIntentPlan?: EncodedBridgeIntentPlan;
}

export interface ProviderPairCapability {
  chainId: number;
  provider: PlannerProvider;
  legType: PlannerLegKind;
  status: 'live' | 'planned' | 'blocked';
  tokenInSymbol: string;
  tokenInAddress: string;
  tokenOutSymbol: string;
  tokenOutAddress: string;
  target?: string;
  providerData?: Record<string, unknown>;
  providerDataHex?: string;
  notes?: string[];
  reason?: string;
}

export interface ProviderCapabilityRecord {
  chainId: number;
  provider: PlannerProvider;
  executionMode: 'onchain' | 'partner';
  live: boolean;
  quoteLive: boolean;
  executionLive: boolean;
  supportedLegTypes: PlannerLegKind[];
  pairs: ProviderPairCapability[];
  notes?: string[];
}

export interface RoutingPolicy {
  profile: ComplianceProfile;
  allowedProviders: PlannerProvider[];
  defaultIntermediateAddresses: string[];
  allowBridge: boolean;
  allowedBridgeLabels: string[];
  maxLegs: number;
  allowCommodityIntermediates: boolean;
  notes: string[];
}

export interface SwapGraphEdge {
  kind: 'swap';
  provider: PlannerProvider;
  chainId: number;
  tokenInAddress: string;
  tokenOutAddress: string;
  tokenInSymbol?: string;
  tokenOutSymbol?: string;
  reserveIn: string;
  reserveOut: string;
  target?: string;
  poolAddress?: string;
  providerData?: Record<string, unknown>;
  providerDataHex?: string;
  totalLiquidityUsd: number;
  freshnessSeconds: number | null;
  notes: string[];
}

export interface BridgeRouteCandidate {
  bridgeType: string;
  bridgeAddress: string;
  bridgeLabel: string;
  assetSymbol: string;
  sourceTokenAddress: string;
  destinationTokenAddress: string;
  fromChainId: number;
  toChainId: number;
  notes: string[];
}
