// =============================================================================
// ImageMagick Adapter
// Converts between various image formats using ImageMagick WASM via Web Worker
// =============================================================================

import * as Comlink from 'comlink';
import type {
  IFileConverter,
  SupportedFormat,
  ConversionRequest,
  ImageFormat,
} from '../core/types';
import { getFormatCategory } from '../core/format-utils';
import type { ImageConverterWorker } from '../workers/image.worker';

type WorkerType = Comlink.Remote<ImageConverterWorker>;
let workerInstance: WorkerType | null = null;

function getWorker(): WorkerType {
  if (!workerInstance) {
    const worker = new Worker(
      new URL('../workers/image.worker.ts', import.meta.url),
      { type: 'module' }
    );
    workerInstance = Comlink.wrap<ImageConverterWorker>(worker);
  }
  return workerInstance;
}

// Formats that ImageMagick can handle (excludes HEIC which uses heic-adapter)
const SUPPORTED_FORMATS: ImageFormat[] = [
  'jpeg', 'png', 'webp', 'gif', 'bmp', 'tiff', 'ico',
  'avif', 'jxl', 'svg', 'psd', 'raw', 'tga'
];

export class ImageMagickAdapter implements IFileConverter {
  readonly name = 'imagemagick-adapter';

  supports(inputFormat: SupportedFormat, outputFormat: SupportedFormat): boolean {
    // Both must be images
    if (getFormatCategory(inputFormat) !== 'image' || getFormatCategory(outputFormat) !== 'image') {
      return false;
    }

    // HEIC input is handled by the specialized HeicAdapter
    if (inputFormat === 'heic') {
      return false;
    }

    return (
      SUPPORTED_FORMATS.includes(inputFormat as ImageFormat) &&
      SUPPORTED_FORMATS.includes(outputFormat as ImageFormat)
    );
  }

  async convert(
    request: ConversionRequest,
    onProgress?: (progress: number) => void
  ): Promise<Blob> {
    const { file, targetFormat, options } = request;
    const quality = options?.quality ?? 85;

    onProgress?.(10);

    // Read file into ArrayBuffer
    const arrayBuffer = await file.arrayBuffer();
    onProgress?.(30);

    // Detect input format from file
    const inputFormat = this.detectInputFormat(file);
    
    const worker = getWorker();
    const result = await worker.convertImage(
      arrayBuffer,
      inputFormat,
      targetFormat as ImageFormat,
      quality
    );

    onProgress?.(100);
    return result;
  }

  private detectInputFormat(file: File): ImageFormat {
    const mimeToFormat: Record<string, ImageFormat> = {
      'image/jpeg': 'jpeg',
      'image/png': 'png',
      'image/webp': 'webp',
      'image/gif': 'gif',
      'image/bmp': 'bmp',
      'image/tiff': 'tiff',
    };

    const format = mimeToFormat[file.type];
    if (format) return format;

    // Fallback to extension
    const ext = file.name.split('.').pop()?.toLowerCase();
    if (ext === 'jpg') return 'jpeg';
    if (ext && SUPPORTED_FORMATS.includes(ext as ImageFormat)) {
      return ext as ImageFormat;
    }

    throw new Error(`Unable to detect format for file: ${file.name}`);
  }
}

// Export singleton instance
export const imageMagickAdapter = new ImageMagickAdapter();
