// =============================================================================
// HEIC Adapter
// Converts HEIC/HEIF images to any image format
// Uses heic2any for HEIC→JPEG/PNG, then ImageMagick worker for further conversion
// =============================================================================

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

// Formats heic2any can directly output
const HEIC2ANY_OUTPUTS: ImageFormat[] = ['jpeg', 'png'];

// All image formats we support as final output (via two-step conversion)
const ALL_IMAGE_OUTPUTS: ImageFormat[] = [
  'jpeg', 'png', 'webp', 'gif', 'bmp', 'tiff', 'ico',
  'avif', 'jxl', 'svg', 'psd', 'tga'
];

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;
}

export class HeicAdapter implements IFileConverter {
  readonly name = 'heic-adapter';

  supports(inputFormat: SupportedFormat, outputFormat: SupportedFormat): boolean {
    return (
      inputFormat === 'heic' &&
      ALL_IMAGE_OUTPUTS.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?.(5);

    try {
      // Step 1: Convert HEIC to intermediate format using heic2any (main thread)
      // Use JPEG as intermediate for efficiency, PNG if target is PNG
      const intermediateFormat = targetFormat === 'png' ? 'png' : 'jpeg';
      const toType = intermediateFormat === 'png' ? 'image/png' : 'image/jpeg';

      let intermediateBlob: Blob;
      try {
        const result = await heic2any({
          blob: file,
          toType,
          quality: quality / 100,
        });
        intermediateBlob = Array.isArray(result) ? result[0] : result;
      } catch (heicError) {
        // heic2any failed - provide helpful error message
        const errorMessage = heicError instanceof Error ? heicError.message : String(heicError);
        if (errorMessage.includes('LIBHEIF') || errorMessage.includes('format not supported')) {
          throw new Error(`This HEIC file format is not supported. Try using a different photo or convert it on your iPhone first.`);
        }
        throw new Error(`Failed to decode HEIC: ${JSON.stringify(errorMessage)}`);
      }

      onProgress?.(50);

      // Step 2: If target is JPEG or PNG, we're done
      if (HEIC2ANY_OUTPUTS.includes(targetFormat as ImageFormat)) {
        onProgress?.(100);
        return intermediateBlob;
      }

      // Step 3: Convert intermediate to final format using ImageMagick worker
      const arrayBuffer = await intermediateBlob.arrayBuffer();
      onProgress?.(70);

      const worker = getWorker();
      const result = await worker.convertImage(
        arrayBuffer,
        intermediateFormat,
        targetFormat as ImageFormat,
        quality
      );

      onProgress?.(100);
      return result;

    } catch (error) {
      // Re-throw with context
      if (error instanceof Error) {
        throw error;
      }
      throw new Error(`HEIC conversion failed: ${String(error)}`);
    }
  }
}

// Export singleton instance
export const heicAdapter = new HeicAdapter();
