import { ethers } from 'ethers';
import * as fs from 'fs';
import * as path from 'path';
import { checkpointAggregatorConfig as cfg } from './config';

export type BatchPayload = {
  batchId: string;
  chainId: number;
  checkpointBlock: number;
  paymentsRoot: string;
  leaves: unknown[];
  submittedAt: string;
  batchTotalUsd?: string;
  usdEnrichedAt?: string;
};

function jsonReplacer(_key: string, value: unknown): unknown {
  return typeof value === 'bigint' ? value.toString() : value;
}

export async function publishBatchPayload(batchId: bigint, payload: BatchPayload): Promise<string> {
  const json = JSON.stringify(payload, jsonReplacer, 2);
  const localDir = cfg.batchPayloadDir;
  fs.mkdirSync(localDir, { recursive: true });
  const localPath = path.join(localDir, `batch-${batchId}.json`);
  fs.writeFileSync(localPath, json);

  if (!cfg.ipfsApiUrl) {
    if (cfg.payloadPublicUrl) {
      const url = `${cfg.payloadPublicUrl.replace(/\/$/, '')}/batch-${batchId}.json`;
      return ethers.keccak256(ethers.toUtf8Bytes(url));
    }
    return ethers.keccak256(ethers.toUtf8Bytes(`file://${localPath}`));
  }

  const form = new FormData();
  form.append('file', new Blob([json], { type: 'application/json' }), `batch-${batchId}.json`);
  const res = await fetch(`${cfg.ipfsApiUrl.replace(/\/$/, '')}/api/v0/add`, { method: 'POST', body: form });
  if (!res.ok) {
    throw new Error(`IPFS add failed: ${res.status} ${await res.text()}`);
  }
  const text = await res.text();
  const line = text.trim().split('\n').pop() || '{}';
  const parsed = JSON.parse(line) as { Hash?: string };
  if (!parsed.Hash) throw new Error('IPFS response missing Hash');
  return ethers.keccak256(ethers.toUtf8Bytes(`ipfs://${parsed.Hash}`));
}
