import {
  enrichLeafUsdFields,
  fetchAllTokenTransfersForTx,
  pickPrimaryFromSummaries,
  type TokenTransferSummary,
  type UsdPricingConfig,
} from '@dbis/checkpoint-core';
import type { PaymentLeaf } from './ingress/types';

export type BlockscoutEnrichResult = {
  allErc20: TokenTransferSummary[];
};

/** Single Blockscout fetch: all transfers + primary token fields on leaf. */
export async function enrichLeafFromBlockscoutApi(
  leaf: PaymentLeaf,
  blockscoutApi: string,
  useBlockscout: boolean
): Promise<BlockscoutEnrichResult> {
  if (!useBlockscout) return { allErc20: [] };
  const allErc20 = await fetchAllTokenTransfersForTx(blockscoutApi, leaf.txHash);
  const primary = pickPrimaryFromSummaries(allErc20);
  if (primary) {
    leaf.token = primary.token;
    leaf.tokenSymbol = primary.tokenSymbol;
    leaf.tokenDecimals = primary.tokenDecimals;
    leaf.tokenValue = primary.value;
    leaf.tokenLogIndex = primary.logIndex;
  }
  return { allErc20 };
}

export async function enrichLeafUsd(
  leaf: PaymentLeaf,
  cfg: UsdPricingConfig & { blockscoutApi: string; useBlockscout: boolean },
  preloaded?: TokenTransferSummary[]
): Promise<void> {
  if (cfg.enabled === false) return;

  let allErc20 = preloaded ?? [];
  if (!preloaded?.length && cfg.useBlockscout) {
    allErc20 = await fetchAllTokenTransfersForTx(cfg.blockscoutApi, leaf.txHash);
  } else if (!preloaded?.length && leaf.token && leaf.tokenValue != null && leaf.tokenValue > 0n) {
    allErc20 = [
      {
        token: leaf.token,
        tokenSymbol: leaf.tokenSymbol || '',
        tokenDecimals: leaf.tokenDecimals ?? 18,
        from: leaf.from,
        to: leaf.to,
        value: leaf.tokenValue,
        logIndex: leaf.tokenLogIndex ?? 0,
      },
    ];
  }

  const record: Record<string, unknown> = {
    txHash: leaf.txHash,
    from: leaf.from,
    to: leaf.to,
    value: leaf.value.toString(),
    nativeValueWei: leaf.value.toString(),
    blockNumber: leaf.blockNumber,
    blockTimestamp: leaf.blockTimestamp,
    gasUsed: leaf.gasUsed.toString(),
    success: leaf.success,
    token: leaf.token,
    tokenSymbol: leaf.tokenSymbol,
    tokenDecimals: leaf.tokenDecimals,
    tokenValue: leaf.tokenValue?.toString(),
    tokenLogIndex: leaf.tokenLogIndex,
  };

  const enriched = await enrichLeafUsdFields(cfg, record, allErc20);
  if (enriched.valueUsd != null) leaf.valueUsd = String(enriched.valueUsd);
  if (enriched.nativeValueUsd != null) leaf.nativeValueUsd = String(enriched.nativeValueUsd);
  if (enriched.tokenValueUsd != null) leaf.tokenValueUsd = String(enriched.tokenValueUsd);
  if (enriched.nativePriceUsd != null) leaf.nativePriceUsd = Number(enriched.nativePriceUsd);
  if (enriched.tokenPriceUsd != null) leaf.tokenPriceUsd = Number(enriched.tokenPriceUsd);
  if (enriched.priceSource != null) leaf.priceSource = String(enriched.priceSource);
  if (enriched.priceEffectiveTimestamp != null) {
    leaf.priceEffectiveTimestamp = String(enriched.priceEffectiveTimestamp);
  }
  if (enriched.totalTransfersUsd != null) leaf.totalTransfersUsd = String(enriched.totalTransfersUsd);
  if (Array.isArray(enriched.transfers)) leaf.transfers = enriched.transfers as Array<Record<string, unknown>>;
  if (enriched.usdEnrichedAt != null) leaf.usdEnrichedAt = String(enriched.usdEnrichedAt);
}
