/**
 * WASM module loader for @drs/wasm (generated by wasm-pack from drs-core).
 *
 * Design principles:
 * - initWasm() is idempotent — safe to call multiple times
 * - getWasmModule() is synchronous after init — no await in hot paths
 * - The WASM module is loaded once and cached; subsequent calls return the same instance
 *
 * Usage:
 *   await initWasm();
 *   const wasm = getWasmModule();
 *   const result = wasm.verify_chain(bundleJson);
 */

/** Opaque type for the WASM module exports. */
export interface WasmModule {
  verify_chain: (bundleJson: string) => string;
}

let wasmModule: WasmModule | null = null;
let initPromise: Promise<void> | null = null;

/**
 * Initialises the WASM module. Idempotent — safe to call multiple times.
 * Must be awaited before calling getWasmModule().
 */
export async function initWasm(wasmUrl?: string): Promise<void> {
  if (wasmModule !== null) {
    return;
  }
  if (initPromise !== null) {
    return initPromise;
  }

  initPromise = (async () => {
    // Dynamic import of @drs/wasm — the package is generated by wasm-pack.
    // The import path is resolved at runtime so the SDK can be used without
    // the WASM package installed (graceful degradation to HTTP verify client).
    try {
      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
      const wasmPkg = await import("@drs/wasm");
      if (wasmUrl !== undefined) {
        // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
        await (wasmPkg as { default: (url?: string) => Promise<void> }).default(wasmUrl);
      } else {
        // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
        await (wasmPkg as { default: () => Promise<void> }).default();
      }
      wasmModule = wasmPkg as unknown as WasmModule;
    } catch (error: unknown) {
      initPromise = null;
      throw new Error(
        `Failed to load @drs/wasm: ${error instanceof Error ? error.message : String(error)}. ` +
          "Install the package or use VerifyClient for server-side verification.",
      );
    }
  })();

  return initPromise;
}

/**
 * Returns the loaded WASM module synchronously.
 * Must be called after awaiting initWasm().
 * Throws if initWasm() has not been called or has not completed.
 */
export function getWasmModule(): WasmModule {
  if (wasmModule === null) {
    throw new Error("WASM module not initialised — call and await initWasm() first.");
  }
  return wasmModule;
}

/** Returns true if the WASM module has been successfully loaded. */
export function isWasmReady(): boolean {
  return wasmModule !== null;
}

/** Resets the WASM module (for testing purposes only). */
export function _resetWasmForTesting(): void {
  wasmModule = null;
  initPromise = null;
}
