/**
 * Photo Compression Utility
 * Client-side image compression before upload per specs/photo-management.md
 */

import imageCompression from 'browser-image-compression';

export interface CompressedPhoto {
    file: File;
    preview: string;
    originalSize: number;
    compressedSize: number;
    savingsPercent: number;
}

export interface CompressionOptions {
    maxSizeMB?: number;
    maxWidthOrHeight?: number;
    quality?: number;
    useWebWorker?: boolean;
}

const DEFAULT_OPTIONS: CompressionOptions = {
    maxSizeMB: 1, // Max 1MB after compression
    maxWidthOrHeight: 1920,
    useWebWorker: true,
};

/**
 * Compress a single photo before upload
 */
export async function compressPhoto(
    file: File,
    options: CompressionOptions = {}
): Promise<CompressedPhoto> {
    const opts = { ...DEFAULT_OPTIONS, ...options };
    const originalSize = file.size;

    try {
        const compressedFile = await imageCompression(file, {
            maxSizeMB: opts.maxSizeMB!,
            maxWidthOrHeight: opts.maxWidthOrHeight!,
            useWebWorker: opts.useWebWorker!,
            fileType: 'image/webp',
        });

        const preview = await createPreview(compressedFile);
        const compressedSize = compressedFile.size;
        const savingsPercent = Math.round((1 - compressedSize / originalSize) * 100);

        return {
            file: compressedFile,
            preview,
            originalSize,
            compressedSize,
            savingsPercent,
        };
    } catch (error) {
        console.error('Photo compression failed:', error);
        // Return original if compression fails
        const preview = await createPreview(file);
        return {
            file,
            preview,
            originalSize,
            compressedSize: originalSize,
            savingsPercent: 0,
        };
    }
}

/**
 * Compress multiple photos
 */
export async function compressPhotos(
    files: File[],
    options: CompressionOptions = {},
    onProgress?: (completed: number, total: number) => void
): Promise<CompressedPhoto[]> {
    const results: CompressedPhoto[] = [];

    for (let i = 0; i < files.length; i++) {
        const result = await compressPhoto(files[i], options);
        results.push(result);
        onProgress?.(i + 1, files.length);
    }

    return results;
}

/**
 * Create a preview URL for an image file
 */
async function createPreview(file: File): Promise<string> {
    return new Promise((resolve) => {
        const reader = new FileReader();
        reader.onloadend = () => resolve(reader.result as string);
        reader.readAsDataURL(file);
    });
}

/**
 * Format file size for display
 */
export function formatFileSize(bytes: number): string {
    if (bytes < 1024) return `${bytes} B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

/**
 * Check if file is a valid image type
 */
export function isValidImageType(file: File): boolean {
    const validTypes = [
        'image/jpeg',
        'image/png',
        'image/webp',
        'image/heic',
        'image/heif',
    ];
    return validTypes.includes(file.type);
}

/**
 * Get image dimensions
 */
export async function getImageDimensions(file: File): Promise<{ width: number; height: number }> {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => {
            resolve({ width: img.width, height: img.height });
            URL.revokeObjectURL(img.src);
        };
        img.onerror = reject;
        img.src = URL.createObjectURL(file);
    });
}
