import { ethers } from 'ethers';
import { usdStringToE8 } from '@dbis/checkpoint-core';
import type { PaymentLeaf } from './ingress/types';
import { effectiveValue } from './leafCodec';

const REGISTRY_ABI = [
  'function recordBatch(uint64 batchId, tuple(bytes32 txHash,address from,address to,uint256 valueWei,uint256 blockNumber138,uint64 blockTimestamp138,uint64 valueUsdE8,uint32 logCount,bytes32 receiptHash)[] records) external',
  'function recorded(bytes32) view returns (bool)',
];

function activityRecord(leaf: PaymentLeaf) {
  const usd = leaf.totalTransfersUsd ?? leaf.valueUsd ?? leaf.nativeValueUsd ?? '0';
  return {
    txHash: leaf.txHash,
    from: leaf.from,
    to: leaf.to,
    valueWei: effectiveValue(leaf),
    blockNumber138: BigInt(leaf.blockNumber),
    blockTimestamp138: BigInt(leaf.blockTimestamp),
    valueUsdE8: usdStringToE8(usd),
    logCount: leaf.logCount ?? 0,
    receiptHash: leaf.receiptHash ?? ethers.ZeroHash,
  };
}

export async function recordActivityBatch(
  wallet: ethers.Wallet,
  registryAddress: string,
  batchId: bigint,
  leaves: PaymentLeaf[]
): Promise<string | null> {
  if (!registryAddress || leaves.length === 0) return null;
  const registry = new ethers.Contract(registryAddress, REGISTRY_ABI, wallet);
  const pending: PaymentLeaf[] = [];
  for (const leaf of leaves) {
    if (!leaf.txHash) continue;
    try {
      if (await registry.recorded(leaf.txHash)) continue;
    } catch {
      /* continue */
    }
    pending.push(leaf);
  }
  if (pending.length === 0) return null;

  const records = pending.map(activityRecord);
  const tx = await registry.recordBatch(batchId, records, { gasLimit: 2_500_000n });
  await tx.wait();
  return tx.hash as string;
}
