import ZkExpoModule from "./ZkExpoModule";

export interface ProofPoint {
  a: [string, string];
  b: [[string, string], [string, string]];
  c: [string, string];
}

export interface ProofResult {
  proof: ProofPoint;
  publicSignals: string[];
}

/**
 * Strips the `file://` scheme and URL-decodes the path so Rust's std::fs
 * can open it. expo-asset returns URIs like
 * `file:///var/mobile/Containers/.../Application%20Support/...`
 * which the OS rejects if passed verbatim to fopen.
 */
function normalizePath(uri: string): string {
  return decodeURIComponent(uri.replace(/^file:\/\//, ""));
}

export async function groth16ProveV2(
  graph_path: string,
  zkey_path: string,
  inputs: string,
): Promise<ProofResult> {
  try {
    const res = await ZkExpoModule.groth16ProveV2(
      normalizePath(graph_path),
      normalizePath(zkey_path),
      inputs,
    );
    const { proof, public_signals } = JSON.parse(res);
    return { proof, publicSignals: public_signals };
  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`, { cause: e });
  }
}

export async function groth16ProveV2Base64(
  graph_b64: string,
  zkey_b64: string,
  inputs: string,
): Promise<ProofResult> {
  try {
    const res = await ZkExpoModule.groth16ProveV2Base64(graph_b64, zkey_b64, inputs);
    const { proof, public_signals } = JSON.parse(res);
    return { proof, publicSignals: public_signals };
  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`, { cause: e });
  }
}

export async function addToCache(
  functionName: "groth16_prove_v2" = "groth16_prove_v2",
  path1: string,
  path2: string,
): Promise<void> {
  try {
    await ZkExpoModule.addToCache(
      functionName,
      normalizePath(path1),
      normalizePath(path2),
    );
  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`, { cause: e });
  }
}

export async function clearCache(): Promise<void> {
  try {
    await ZkExpoModule.clearCache();
  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`, { cause: e });
  }
}
