let wasmModule: typeof import('./wasm/flowscope_wasm') | null = null;
let initPromise: Promise<typeof import('./wasm/flowscope_wasm')> | null = null;

export interface InitWasmOptions {
  wasmUrl?: string;
  enableTracing?: boolean;
}

/**
 * Initialize the WASM module. Safe to call multiple times (idempotent).
 * Returns the initialized WASM module.
 */
export async function initWasm(
  options: InitWasmOptions = {}
): Promise<typeof import('./wasm/flowscope_wasm')> {
  // Return cached module if already initialized
  if (wasmModule) {
    return wasmModule;
  }

  // Return existing promise if initialization is in progress
  if (initPromise) {
    return initPromise;
  }

  initPromise = (async () => {
    try {
      // Dynamic import of the wasm module
      // With vite-plugin-wasm, the module auto-initializes on import
      const wasm = await import('./wasm/flowscope_wasm');

      // Explicitly initialize the WASM module
      if (typeof wasm.default === 'function') {
        // Pass through custom URL when provided so host apps can control asset location
        await wasm.default(options.wasmUrl ?? undefined);
        // Allow host apps to enable tracing via init option if supported by the build
        const wasmWithTracing = wasm as typeof wasm & { enable_tracing?: () => void };
        if (options.enableTracing && typeof wasmWithTracing.enable_tracing === 'function') {
          wasmWithTracing.enable_tracing();
        }
      }

      // Verify that the module is actually initialized by checking for required functions
      if (!wasm.analyze_sql_json || typeof wasm.analyze_sql_json !== 'function') {
        throw new Error('WASM module loaded but analyze_sql_json function is not available');
      }

      wasmModule = wasm;
      return wasmModule;
    } catch (error) {
      initPromise = null; // Allow retry on failure
      throw new Error(
        `Failed to initialize WASM module: ${error instanceof Error ? error.message : String(error)}`
      );
    }
  })();

  return initPromise;
}

/**
 * Check if WASM module is initialized
 */
export function isWasmInitialized(): boolean {
  return wasmModule !== null;
}

/**
 * Get the initialized WASM module. Throws if not initialized.
 */
export function getWasmModule(): typeof import('./wasm/flowscope_wasm') {
  if (!wasmModule) {
    throw new Error('WASM module not initialized. Call initWasm() first.');
  }
  return wasmModule;
}

/**
 * Get the version of the underlying Rust engine.
 * Throws if WASM is not initialized.
 */
export function getEngineVersion(): string {
  const wasm = getWasmModule();
  if (typeof wasm.get_version === 'function') {
    return wasm.get_version();
  }
  return 'unknown';
}

/**
 * Cleanup the WASM module and release resources
 */
export async function cleanupWasm(): Promise<void> {
  if (wasmModule) {
    // Check if the module has a cleanup/free method and call it
    type WasmModuleWithCleanup = typeof wasmModule & { __wbindgen_free?: () => void };
    const moduleWithCleanup = wasmModule as WasmModuleWithCleanup;
    if (typeof moduleWithCleanup.__wbindgen_free !== 'undefined') {
      try {
        // WASM modules generated by wasm-bindgen typically have cleanup methods
        // This is a best-effort cleanup
        moduleWithCleanup.__wbindgen_free?.();
      } catch (error) {
        // Cleanup errors are non-critical but log in development for debugging
        const isDev =
          typeof globalThis !== 'undefined' &&
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          (globalThis as any).process?.env?.NODE_ENV === 'development';
        if (isDev) {
          console.warn('WASM cleanup error (non-critical):', error);
        }
      }
    }
  }
  wasmModule = null;
  initPromise = null;
}

/**
 * Reset the WASM module (mainly for testing)
 */
export function resetWasm(): void {
  wasmModule = null;
  initPromise = null;
}
