import type { CanonicalPaymentMessage } from '@dbis/checkpoint-core';

export type SwiftFinMessageType =
  | 'MT103'
  | 'MT202'
  | 'MT910'
  | 'MT940'
  | 'MT942'
  | 'MT950'
  | 'UNKNOWN';

export type Iso20022MessageType =
  | 'pain.001'
  | 'pacs.008'
  | 'pacs.009'
  | 'pacs.002'
  | 'camt.052'
  | 'camt.053'
  | 'camt.054'
  | 'unknown';

export type InboundFormat = 'swift_fin' | 'iso20022' | 'json_broadcast' | 'ktt';

export type KttMessageType = 'KTT' | 'TELEX_KTT';

export type ResourceMatchKind =
  | 'chain138_name'
  | 'chain138_address'
  | 'chain138_symbol'
  | 'cw_symbol'
  | 'cw_address'
  | 'instruction_prefix'
  | 'remittance_keyword'
  | 'contract_ref';

export type ResourceMatch = {
  kind: ResourceMatchKind;
  value: string;
  field: string;
  symbol?: string;
  chainId?: number;
};

export type ParsedSwiftFin = {
  format: 'swift_fin';
  messageType: SwiftFinMessageType;
  raw: string;
  parsed: Record<string, unknown>;
  searchableText: string;
};

export type ParsedIso20022 = {
  format: 'iso20022';
  messageType: Iso20022MessageType;
  raw: string;
  parsed: Record<string, unknown>;
  searchableText: string;
};

export type ParsedJsonBroadcast = {
  format: 'json_broadcast';
  messageType: string;
  raw: string;
  parsed: Record<string, unknown>;
  searchableText: string;
};

export type ParsedKtt = {
  format: 'ktt';
  messageType: KttMessageType;
  raw: string;
  parsed: Record<string, unknown>;
  searchableText: string;
  testKeyProof?: string;
  authAttestationHash?: string;
};

export type ParsedInbound = ParsedSwiftFin | ParsedIso20022 | ParsedJsonBroadcast | ParsedKtt;

export type SwiftListenerEvent = {
  id: string;
  receivedAt: string;
  source: string;
  format: InboundFormat;
  messageType: string;
  matched: boolean;
  matches: ResourceMatch[];
  parsed: Record<string, unknown>;
  canonical?: CanonicalPaymentMessage;
  rawPreview: string;
  dedupeKey: string;
  outbound?: OutboundDispatchResult;
};

export type OutboundDispatchResult = {
  omnl?: { stored?: string; apiStatus?: number; apiPath?: string; error?: string };
  intakeGateway?: {
    dryRun: boolean;
    txHash?: string;
    error?: string;
    gateway?: string;
    prepared?: boolean;
  };
};

export type ListenerConfig = {
  schemaVersion: string;
  chain138: {
    chainId: number;
    names: string[];
    rpcHint?: string;
    configSources?: string[];
  };
  supportedSwiftFinTypes: SwiftFinMessageType[];
  supportedIso20022Types: Iso20022MessageType[];
  cToCwSymbolMapping: Record<string, string>;
  matchHints: {
    instructionIdPrefixes: string[];
    remittanceKeywords: string[];
  };
  storage: {
    eventsDir: string;
    latestStatus: string;
    processedIndex: string;
    inboxDir: string;
    archiveDir: string;
    as4InboxDir?: string;
    mailInboxDir?: string;
    telexInboxDir?: string;
  };
  adapters: {
    fileInbox: { enabled: boolean; pollIntervalSec: number; archiveOnProcess?: boolean };
    webhook: {
      enabled: boolean;
      port: number;
      path: string;
      healthPath?: string;
      authBearerEnv?: string;
      webhookSecretEnv?: string;
      webhookSignatureHeader?: string;
    };
    p2pRail: {
      enabled: boolean;
      baseUrlEnv: string;
      pollIntervalSec: number;
      transactionsPath: string;
    };
    finGateway: {
      enabled: boolean;
      baseUrlEnv: string;
      fallbackBaseUrlEnv?: string;
      pollIntervalSec: number;
      messagesPath: string;
      authBearerEnv?: string;
    };
    swiftFinTcp: {
      enabled: boolean;
      host: string;
      portEnv: string;
      defaultPort: number;
    };
    as4Inbox: {
      enabled: boolean;
      pollIntervalSec: number;
      archiveOnProcess?: boolean;
    };
    mailAttachmentInbox: {
      enabled: boolean;
      pollIntervalSec: number;
      archiveOnProcess?: boolean;
    };
    telexInbox: {
      enabled: boolean;
      pollIntervalSec: number;
      archiveOnProcess?: boolean;
    };
  };
  outbound?: {
    omnlForward: {
      enabled: boolean;
      mode: 'local' | 'api' | 'local_and_api';
      apiPath?: string;
      tokenAggregationUrlEnv: string;
      apiKeyEnv: string;
      localStoreDir: string;
    };
    intakeGateway: {
      enabled: boolean;
      gatewayAddressEnv: string;
      gatewayAddressFallback: string;
      rpcUrlEnv: string;
      privateKeyEnv: string;
      executeEnv: string;
      dryRunDefault: boolean;
      autoExecuteWhenKeyPresent?: boolean;
      chainId: number;
    };
  };
  /** @deprecated use outbound.omnlForward */
  omnlForward?: {
    enabled: boolean;
    tokenAggregationUrlEnv: string;
    apiKeyEnv: string;
  };
};

export type ResourceRegistry = {
  chainId: number;
  chainNames: string[];
  symbols: Set<string>;
  cwSymbols: Set<string>;
  addresses: Map<string, { symbol?: string; chainId?: number }>;
  instructionPrefixes: string[];
  remittanceKeywords: string[];
  contracts: string[];
};

export type SwiftListenerOptions = {
  /** Process one batch and return (for --once). */
  once?: boolean;
};

export type InboundMessage = {
  source: string;
  format: InboundFormat;
  payload: string;
  metadata?: Record<string, unknown>;
};
