import type { ConverterEngine, WASMModuleState } from '@/types/media';
import type { FFmpeg as FFmpegType } from '@ffmpeg/ffmpeg';
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { initializeImageMagick } from '@imagemagick/magick-wasm';
import { toBlobURL } from '@ffmpeg/util';

/**
 * WASM module loading state
 */
const moduleState: WASMModuleState = {
  ffmpeg: false,
  imagemagick: false,
};

/**
 * Cached WASM instances
 */
let ffmpegInstance: FFmpegType | null = null;
let imagemagickInstance: any = null;

/**
 * Load FFmpeg WASM module
 */
export async function loadFFmpeg(): Promise<FFmpegType> {
  if (ffmpegInstance && moduleState.ffmpeg) {
    return ffmpegInstance;
  }

  try {
    if (!FFmpeg) {
      throw new Error('FFmpeg class not available');
    }

    ffmpegInstance = new FFmpeg();

    if (!ffmpegInstance) {
      throw new Error('Failed to create FFmpeg instance');
    }

    ffmpegInstance.on('log', ({ message }: { message: string }) => {
      console.log('[FFmpeg]', message);
    });

    // Use CDN URLs for FFmpeg core - avoids "dynamic require" bundler issues
    // with local file paths that FFmpeg's internal code cannot resolve at runtime
    const coreURL = '/wasm/ffmpeg-core.js';
    const wasmURL = '/wasm/ffmpeg-core.wasm';

    await ffmpegInstance.load({ 
      coreURL: await toBlobURL(coreURL, 'text/javascript'),
      wasmURL: await toBlobURL(wasmURL, 'application/wasm')
    });

    moduleState.ffmpeg = true;
    console.log('[FFmpeg] Loaded successfully from local assets');

    return ffmpegInstance;
  } catch (error) {
    console.error('[FFmpeg] Failed to load:', error);
    throw new Error('Failed to load FFmpeg WASM module');
  }
}

/**
 * Load ImageMagick WASM module
 */
export async function loadImageMagick(): Promise<any> {
  if (imagemagickInstance && moduleState.imagemagick) {
    return imagemagickInstance;
  }

  try {
    // File is guaranteed to exist in /wasm/ by the postinstall script
    const wasmUrl = '/wasm/magick.wasm';

    console.log('[ImageMagick] Loading local WASM:', wasmUrl);

    const response = await fetch(wasmUrl);
    if (!response.ok) {
      throw new Error(`Failed to fetch WASM file: ${response.status} ${response.statusText}`);
    }

    const arrayBuffer = await response.arrayBuffer();
    console.log('[ImageMagick] WASM file size:', arrayBuffer.byteLength, 'bytes');
    
    await initializeImageMagick(arrayBuffer);

    // Store the module for later use
    imagemagickInstance = { initialized: true };
    moduleState.imagemagick = true;
    console.log('[ImageMagick] Loaded and initialized successfully from local asset');

    return imagemagickInstance;
  } catch (error) {
    console.error('[ImageMagick] Failed to load:', error);
    throw new Error(`Failed to load ImageMagick WASM module: ${error instanceof Error ? error.message : 'Unknown error'}`);
  }
}

/**
 * Get loaded module state
 */
export function getModuleState(): WASMModuleState {
  return { ...moduleState };
}

/**
 * Check if a specific module is loaded
 */
export function isModuleLoaded(engine: ConverterEngine): boolean {
  return moduleState[engine];
}

/**
 * Load appropriate WASM module for converter engine
 */
export async function loadModule(engine: ConverterEngine): Promise<any> {
  switch (engine) {
    case 'ffmpeg':
      return loadFFmpeg();
    case 'imagemagick':
      return loadImageMagick();
    default:
      throw new Error(`Unknown converter engine: ${engine}`);
  }
}

/**
 * Unload all WASM modules and free memory
 */
export function unloadAll(): void {
  if (ffmpegInstance) {
    // FFmpeg doesn't have an explicit unload method
    // Just null the instance
    ffmpegInstance = null;
    moduleState.ffmpeg = false;
  }

  if (imagemagickInstance) {
    imagemagickInstance = null;
    moduleState.imagemagick = false;
  }

  console.log('All WASM modules unloaded');
}
