import { keccak256, type Address, type Hex } from "viem";
import type { AgentConfig } from "./config.js";
import { createChainClients } from "./chain.js";

type ChainClients = ReturnType<typeof createChainClients>;

/**
 * Persist the deterministic transaction hash before broadcasting so a crash
 * cannot leave an onchain action with no local recovery handle.
 */
export const sendTrackedTransaction = async (
  config: AgentConfig,
  clients: ChainClients,
  transaction: { to: Address; data: Hex; value?: bigint },
  onPrepared: (hash: `0x${string}`) => void | Promise<void>,
) => {
  if (!config.account || !clients.walletClient) throw new Error("Wallet client is unavailable in live mode");
  const request = await clients.walletClient.prepareTransactionRequest({
    account: config.account,
    to: transaction.to,
    data: transaction.data,
    ...(transaction.value !== undefined ? { value: transaction.value } : {}),
  });
  const serialized = await clients.walletClient.signTransaction(request);
  const hash = keccak256(serialized);
  await onPrepared(hash);
  const submittedHash = await clients.publicClient.sendRawTransaction({ serializedTransaction: serialized });
  if (submittedHash.toLowerCase() !== hash.toLowerCase()) {
    throw new Error(`RPC returned transaction hash ${submittedHash}, expected ${hash}`);
  }
  return hash;
};
