import { describe, it, expect } from 'vitest';
import { validateImageFile, MAX_FILE_BYTES, formatBytes } from './upload-validation';

function makeFile(name: string, type: string, size: number): File {
    // jsdom's File doesn't honour `size` from a tiny Blob, so we expose
    // the desired size by overriding the getter on the constructed File.
    const f = new File([new Uint8Array(0)], name, { type });
    Object.defineProperty(f, 'size', { value: size });
    return f;
}

describe('validateImageFile', () => {
    it('returns null for a small image', () => {
        const f = makeFile('cover.png', 'image/png', 1024);
        expect(validateImageFile(f)).toBeNull();
    });

    it('rejects oversized files with a sized message', () => {
        const f = makeFile('cover.png', 'image/png', MAX_FILE_BYTES + 1);
        const err = validateImageFile(f);
        expect(err).toContain('cover.png');
        expect(err).toContain('too large');
    });

    it('rejects non-image MIME types', () => {
        const f = makeFile('doc.pdf', 'application/pdf', 1024);
        const err = validateImageFile(f);
        expect(err).toContain('unsupported image type');
        expect(err).toContain('application/pdf');
    });

    it('allows files with unknown MIME (lets the backend sniff decide)', () => {
        const f = makeFile('mystery.bin', '', 1024);
        expect(validateImageFile(f)).toBeNull();
    });

    it.each(['image/jpeg', 'image/png', 'image/webp', 'image/gif', 'image/avif'])(
        'allows %s',
        (type) => {
            const f = makeFile('x', type, 1024);
            expect(validateImageFile(f)).toBeNull();
        }
    );
});

describe('formatBytes', () => {
    it('formats KiB and MiB sensibly', () => {
        expect(formatBytes(512)).toBe('512 B');
        expect(formatBytes(2048)).toBe('2 KiB');
        expect(formatBytes(5 * 1024 * 1024)).toBe('5.0 MiB');
    });

    it('scales up to GiB and TiB for large storage totals', () => {
        expect(formatBytes(6 * 1024 ** 3)).toBe('6.0 GiB');
        expect(formatBytes(Math.round(1.5 * 1024 ** 4))).toBe('1.5 TiB');
    });
});
