// =============================================================================
// Image Worker
// Handles image conversions using ImageMagick WASM
// Note: heic2any doesn't work in workers (requires window), so HEIC is handled
// by the main thread adapter using Canvas API or separate solution
// =============================================================================

import * as Comlink from 'comlink';
import {
  initializeImageMagick,
  ImageMagick,
  MagickFormat,
  MagickGeometry,
} from '@imagemagick/magick-wasm';

// All supported image formats
type ImageFormat = 
  | 'jpeg' | 'png' | 'webp' | 'gif' | 'bmp' | 'tiff' | 'heic' | 'ico'
  | 'avif' | 'jxl' | 'svg' | 'psd' | 'raw' | 'tga';

let magickInitialized = false;
let initPromise: Promise<void> | null = null;

async function ensureMagickInitialized(): Promise<void> {
  if (magickInitialized) return;
  if (initPromise) return initPromise;

  initPromise = (async () => {
    // Use local WASM from public folder (works offline)
    const response = await fetch('/wasm/magick.wasm');
    const wasmBytes = new Uint8Array(await response.arrayBuffer());
    
    await initializeImageMagick(wasmBytes);
    magickInitialized = true;
    console.log('[ImageWorker] ImageMagick WASM initialized');
  })();

  return initPromise;
}

function getMagickFormat(format: ImageFormat): MagickFormat {
  const formatMap: Record<ImageFormat, MagickFormat> = {
    jpeg: MagickFormat.Jpeg,
    png: MagickFormat.Png,
    webp: MagickFormat.WebP,
    gif: MagickFormat.Gif,
    bmp: MagickFormat.Bmp,
    tiff: MagickFormat.Tiff,
    heic: MagickFormat.Heic,
    ico: MagickFormat.Ico,
    avif: MagickFormat.Avif,
    jxl: MagickFormat.Jxl,
    svg: MagickFormat.Svg,
    psd: MagickFormat.Psd,
    raw: MagickFormat.Raw, // Note: May need specific raw format handling
    tga: MagickFormat.Tga,
  };
  return formatMap[format];
}

function getMimeType(format: ImageFormat): string {
  const mimeMap: Record<ImageFormat, string> = {
    jpeg: 'image/jpeg',
    png: 'image/png',
    webp: 'image/webp',
    gif: 'image/gif',
    bmp: 'image/bmp',
    tiff: 'image/tiff',
    heic: 'image/heic',
    ico: 'image/x-icon',
    avif: 'image/avif',
    jxl: 'image/jxl',
    svg: 'image/svg+xml',
    psd: 'image/vnd.adobe.photoshop',
    raw: 'image/x-raw',
    tga: 'image/x-tga',
  };
  return mimeMap[format];
}

const imageConverter = {
  /**
   * Initialize the worker (can be called early to warm up)
   */
  async init(): Promise<boolean> {
    try {
      await ensureMagickInitialized();
      return true;
    } catch (error) {
      console.error('[ImageWorker] Init failed:', error);
      return false;
    }
  },

  /**
   * Convert image using ImageMagick WASM
   */
  async convertImage(
    arrayBuffer: ArrayBuffer,
    _inputFormat: ImageFormat,
    outputFormat: ImageFormat,
    quality: number = 85
  ): Promise<Blob> {
    await ensureMagickInitialized();

    const inputData = new Uint8Array(arrayBuffer);
    const outputMagickFormat = getMagickFormat(outputFormat);

    return new Promise((resolve, reject) => {
      try {
        ImageMagick.read(inputData, (image) => {
          // ICO format has max size of 256x256
          if (outputFormat === 'ico' && (image.width > 256 || image.height > 256)) {
            const geometry = new MagickGeometry(256, 256);
            geometry.ignoreAspectRatio = false;
            image.resize(geometry);
          }

          // Set quality for lossy formats
          if (['jpeg', 'webp', 'avif', 'jxl'].includes(outputFormat)) {
            image.quality = quality;
          }

          image.write(outputMagickFormat, (data) => {
            // Copy to regular ArrayBuffer to avoid SharedArrayBuffer issues
            const buffer = new ArrayBuffer(data.length);
            new Uint8Array(buffer).set(data);
            const blob = new Blob([buffer], { type: getMimeType(outputFormat) });
            resolve(blob);
          });
        });
      } catch (error) {
        reject(error);
      }
    });
  },

  /**
   * Resize image using ImageMagick
   */
  async resizeImage(
    arrayBuffer: ArrayBuffer,
    width: number,
    height: number,
    outputFormat: ImageFormat,
    quality: number = 85
  ): Promise<Blob> {
    await ensureMagickInitialized();

    const inputData = new Uint8Array(arrayBuffer);
    const outputMagickFormat = getMagickFormat(outputFormat);

    return new Promise((resolve, reject) => {
      try {
        ImageMagick.read(inputData, (image) => {
          const geometry = new MagickGeometry(width, height);
          geometry.ignoreAspectRatio = false;
          image.resize(geometry);

          if (['jpeg', 'webp', 'avif', 'jxl'].includes(outputFormat)) {
            image.quality = quality;
          }

          image.write(outputMagickFormat, (data) => {
            const buffer = new ArrayBuffer(data.length);
            new Uint8Array(buffer).set(data);
            const blob = new Blob([buffer], { type: getMimeType(outputFormat) });
            resolve(blob);
          });
        });
      } catch (error) {
        reject(error);
      }
    });
  },
};

Comlink.expose(imageConverter);

export type ImageConverterWorker = typeof imageConverter;