// Client-side preflight for uploads. Mirrors the backend's whitelist so
// obviously bad files don't make a doomed multipart round-trip; the
// backend's magic-byte sniff (in /api/v1/mangas and /chapters) stays the
// authoritative check and surfaces its own error envelope when the
// client-supplied MIME is misleading.

export const MAX_FILE_BYTES = 20 * 1024 * 1024; // 20 MiB

export const ALLOWED_IMAGE_TYPES = [
    'image/jpeg',
    'image/png',
    'image/webp',
    'image/gif',
    'image/avif'
] as const;

export type ImageType = (typeof ALLOWED_IMAGE_TYPES)[number];

/** Binary (1024-based) human byte size. Scales up to TiB so it can format
 *  whole-manga / whole-chapter storage totals, not just upload limits. */
export function formatBytes(n: number): string {
    if (n >= 1024 ** 4) return `${(n / 1024 ** 4).toFixed(1)} TiB`;
    if (n >= 1024 ** 3) return `${(n / 1024 ** 3).toFixed(1)} GiB`;
    if (n >= 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MiB`;
    if (n >= 1024) return `${(n / 1024).toFixed(0)} KiB`;
    return `${n} B`;
}

/**
 * Returns an error message if `file` is obviously unsuitable, or null
 * if it should be allowed through to the multipart request. An unknown
 * file.type (empty string — happens on some drag sources) is treated as
 * "let the backend sniff decide".
 */
export function validateImageFile(file: File): string | null {
    if (file.size > MAX_FILE_BYTES) {
        return `${file.name} is too large (${formatBytes(file.size)} > ${formatBytes(MAX_FILE_BYTES)}).`;
    }
    if (file.type && !(ALLOWED_IMAGE_TYPES as readonly string[]).includes(file.type)) {
        return `${file.name}: unsupported image type ${file.type}.`;
    }
    return null;
}
