import { ethers } from 'ethers';
import { merkleProofs, merkleVerifyValueWei, paymentLeafV1Hash } from '@dbis/checkpoint-core';

const HUB_ABI = [
  'function verifyPaymentInBatch(uint64 batchId, tuple(bytes32,address,address,uint256,uint256,uint64,uint256,bool) leaf, bytes32[] proof) view returns (bool)',
  'function isTxIncluded(bytes32 txHash) view returns (bool included, uint64 batchId)',
  'function getLatestBatchId() view returns (uint64)',
];

export type LeafRecord = Record<string, unknown>;

/**
 * Client-side / indexer-assisted verification before high-value UI.
 */
export async function verifyPaymentInBatch(
  hub: ethers.Contract | string,
  provider: ethers.Provider,
  batchId: bigint | number,
  leaf: LeafRecord,
  proof?: string[]
): Promise<boolean> {
  const contract =
    typeof hub === 'string' ? new ethers.Contract(hub, HUB_ABI, provider) : hub;
  const chainId = Number(leaf.chainId ?? 138);
  const leafTuple = [
    leaf.txHash,
    leaf.from,
    leaf.to,
    merkleVerifyValueWei(leaf),
    BigInt(String(leaf.blockNumber)),
    BigInt(String(leaf.blockTimestamp)),
    BigInt(String(leaf.gasUsed ?? 0)),
    Boolean(leaf.success),
  ];
  const proofs =
    proof ??
    (() => {
      const h = paymentLeafV1Hash(chainId, {
        txHash: String(leaf.txHash),
        from: String(leaf.from),
        to: String(leaf.to),
        value: merkleVerifyValueWei(leaf),
        blockNumber: leaf.blockNumber as number,
        blockTimestamp: leaf.blockTimestamp as number,
        gasUsed: leaf.gasUsed as bigint,
        success: Boolean(leaf.success),
      });
      return merkleProofs([h]).proofs[0];
    })();
  return contract.verifyPaymentInBatch(batchId, leafTuple, proofs);
}

export async function fetchAttestation(
  indexerBase: string,
  txHash: string
): Promise<unknown> {
  const base = indexerBase.replace(/\/$/, '');
  const res = await fetch(`${base}/v1/tx/${txHash}/attestation`);
  if (!res.ok) throw new Error(`indexer ${res.status}`);
  return res.json();
}

export const WALLET_ATTESTATION_COPY =
  'Balances and payments as of Chain 138 checkpoint block in this batch, attested on Ethereum mainnet.';
