import { loadImageMagick } from '@/lib/wasm/wasmLoader';
import type { ConversionOptions, ProgressCallback, ConversionResult } from '@/types/conversion';

/**
 * Convert image using ImageMagick
 */
export async function convertWithImageMagick(
  file: File,
  outputFormat: string,
  options: ConversionOptions = {},
  onProgress?: ProgressCallback
): Promise<ConversionResult> {
  const startTime = Date.now();

  try {
    // Load ImageMagick instance
    await loadImageMagick();

    // Report initial progress
    if (onProgress) onProgress(10);

    // Read input file as ArrayBuffer
    const arrayBuffer = await file.arrayBuffer();
    const inputData = new Uint8Array(arrayBuffer);

    if (onProgress) onProgress(30);

    // Import ImageMagick functions (already initialized by loadImageMagick)
    const { ImageMagick } = await import('@imagemagick/magick-wasm');

    if (onProgress) onProgress(40);

    // Get output format enum
    const outputFormatEnum = await getMagickFormatEnum(outputFormat);

    if (onProgress) onProgress(50);

    // Convert image using ImageMagick
    let result: Uint8Array | undefined;

    await ImageMagick.read(inputData, (image) => {
      // Apply quality setting if specified
      if (options.imageQuality !== undefined) {
        image.quality = options.imageQuality;
      }

      // Apply resize if specified
      if (options.imageWidth || options.imageHeight) {
        const width = options.imageWidth || 0;
        const height = options.imageHeight || 0;

        if (width > 0 && height > 0) {
          // Both dimensions specified
          image.resize(width, height);
        } else if (width > 0) {
          // Only width specified, maintain aspect ratio
          const aspectRatio = image.height / image.width;
          image.resize(width, Math.round(width * aspectRatio));
        } else if (height > 0) {
          // Only height specified, maintain aspect ratio
          const aspectRatio = image.width / image.height;
          image.resize(Math.round(height * aspectRatio), height);
        }
      }

      if (onProgress) onProgress(70);

      // Write the image data with the specified format
      result = image.write(outputFormatEnum);

      if (onProgress) onProgress(90);
    });

    // Verify we have a result
    if (!result || result.length === 0) {
      throw new Error('ImageMagick conversion produced empty result');
    }

    console.log('[ImageMagick] Conversion complete:', {
      inputSize: inputData.length,
      outputSize: result.length,
      format: outputFormat,
      quality: options.imageQuality,
    });

    // Verify the data looks like valid image data by checking magic bytes
    const first4Bytes = Array.from(result.slice(0, 4)).map(b => b.toString(16).padStart(2, '0')).join(' ');
    console.log('[ImageMagick] First 4 bytes:', first4Bytes);

    // Create blob from result
    const mimeType = getMimeType(outputFormat);
    const blob = new Blob([result as BlobPart], { type: mimeType });

    console.log('[ImageMagick] Created blob:', {
      size: blob.size,
      type: blob.type,
    });

    // Verify blob can be read
    try {
      const testReader = new FileReader();
      const testPromise = new Promise((resolve) => {
        testReader.onloadend = () => {
          if (testReader.result instanceof ArrayBuffer) {
            const testArr = new Uint8Array(testReader.result);
            console.log('[ImageMagick] Blob verification - first 4 bytes:',
              Array.from(testArr.slice(0, 4)).map(b => b.toString(16).padStart(2, '0')).join(' '));
          }
          resolve(true);
        };
      });
      testReader.readAsArrayBuffer(blob.slice(0, 4));
      await testPromise;
    } catch (err) {
      console.error('[ImageMagick] Blob verification failed:', err);
    }

    if (onProgress) onProgress(100);

    const duration = Date.now() - startTime;

    return {
      success: true,
      blob,
      duration,
    };
  } catch (error) {
    console.error('[ImageMagick] Conversion error:', error);

    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown conversion error',
      duration: Date.now() - startTime,
    };
  }
}

/**
 * Get ImageMagick format enum
 */
async function getMagickFormatEnum(format: string): Promise<any> {
  const { MagickFormat } = await import('@imagemagick/magick-wasm');

  const formatMap: Record<string, any> = {
    png: MagickFormat.Png,
    jpg: MagickFormat.Jpg,
    jpeg: MagickFormat.Jpg,
    webp: MagickFormat.WebP,
    gif: MagickFormat.Gif,
    bmp: MagickFormat.Bmp,
    tiff: MagickFormat.Tiff,
    svg: MagickFormat.Svg,
  };

  return formatMap[format.toLowerCase()] || MagickFormat.Png;
}

/**
 * Get MIME type for output format
 */
function getMimeType(format: string): string {
  const mimeTypes: Record<string, string> = {
    png: 'image/png',
    jpg: 'image/jpeg',
    jpeg: 'image/jpeg',
    webp: 'image/webp',
    gif: 'image/gif',
    bmp: 'image/bmp',
    tiff: 'image/tiff',
    svg: 'image/svg+xml',
  };

  return mimeTypes[format.toLowerCase()] || 'application/octet-stream';
}

/**
 * Resize image
 */
export async function resizeImage(
  file: File,
  width: number,
  height: number,
  outputFormat?: string,
  onProgress?: ProgressCallback
): Promise<ConversionResult> {
  const format = outputFormat || file.name.split('.').pop() || 'png';

  return convertWithImageMagick(
    file,
    format,
    {
      imageWidth: width,
      imageHeight: height,
    },
    onProgress
  );
}

/**
 * Convert image to WebP
 */
export async function convertToWebP(
  file: File,
  quality: number = 85,
  onProgress?: ProgressCallback
): Promise<ConversionResult> {
  return convertWithImageMagick(
    file,
    'webp',
    {
      imageQuality: quality,
    },
    onProgress
  );
}

/**
 * Batch convert images
 */
export async function batchConvertImages(
  files: File[],
  outputFormat: string,
  options: ConversionOptions = {},
  onProgress?: (fileIndex: number, progress: number) => void
): Promise<ConversionResult[]> {
  const results: ConversionResult[] = [];

  for (let i = 0; i < files.length; i++) {
    const file = files[i];

    const result = await convertWithImageMagick(
      file,
      outputFormat,
      options,
      (progress) => {
        if (onProgress) {
          onProgress(i, progress);
        }
      }
    );

    results.push(result);
  }

  return results;
}
