import {
  createDefaultLearnitiveProjectConfig,
  MemoryProjectStorage,
  projectFilePath,
} from '@learnitive/project-storage';
import { describe, expect, it } from 'vitest';
import {
  getProjectImageFormat,
  importProjectImage,
  normalizeProjectImageFileName,
} from '../image-assets';

describe('project image assets', () => {
  it('recognizes browser and LaTeX image formats case-insensitively', () => {
    expect(getProjectImageFormat('plot.PNG')).toBe('png');
    expect(getProjectImageFormat('photo.jpg')).toBe('jpg');
    expect(getProjectImageFormat('photo.JPEG')).toBe('jpeg');
    expect(getProjectImageFormat('diagram.svg')).toBe('svg');
    expect(getProjectImageFormat('legacy.EPS')).toBe('eps');
    expect(getProjectImageFormat('paper.PDF')).toBe('pdf');
    expect(getProjectImageFormat('photo.webp')).toBeUndefined();
  });

  it('normalizes unsafe display names without changing the image format', () => {
    expect(normalizeProjectImageFileName('Screen Shot (Final) 01.PNG')).toBe(
      'Screen-Shot-Final-01.png',
    );
    expect(normalizeProjectImageFileName('../résumé diagram.svg')).toBe(
      'resume-diagram.svg',
    );
  });

  it('stores binary data in the configured asset directory and avoids collisions', async () => {
    const storage = new MemoryProjectStorage();
    const config = createDefaultLearnitiveProjectConfig();
    const firstBytes = new Uint8Array([0, 255, 2, 17]);
    const secondBytes = new Uint8Array([9, 8, 7]);

    const first = await importProjectImage(storage, config, {
      fileName: 'Result Plot.PNG',
      data: firstBytes,
    });
    const second = await importProjectImage(storage, config, {
      fileName: 'Result Plot.PNG',
      data: secondBytes,
    });

    expect(first.path).toBe('figures/Result-Plot.png');
    expect(second.path).toBe('figures/Result-Plot-2.png');
    expect(await storage.readFile(projectFilePath(first.path))).toEqual(
      firstBytes,
    );
    expect(await storage.readFile(projectFilePath(second.path))).toEqual(
      secondBytes,
    );
  });

  it('does not mutate storage when cancelled before import', async () => {
    const storage = new MemoryProjectStorage();
    const controller = new AbortController();
    controller.abort(new Error('cancelled'));

    await expect(
      importProjectImage(storage, createDefaultLearnitiveProjectConfig(), {
        fileName: 'plot.pdf',
        data: new Uint8Array([1]),
        signal: controller.signal,
      }),
    ).rejects.toThrow('cancelled');
    expect(await storage.listEntries()).toEqual([]);
  });
});
