import { test } from 'node:test';
import assert from 'node:assert/strict';
import { filesFromEntries } from './fileEntries';

const fileEntry = (name: string): FileSystemFileEntry =>
  ({
    isFile: true,
    isDirectory: false,
    name,
    file: (success: (file: File) => void) => {
      success(new File(['x'], name, { type: 'text/plain' }));
    },
  }) as unknown as FileSystemFileEntry;

/**
 * A directory whose reader yields its children in several batches (mirroring
 * Chromium's `readEntries`, which caps each call) and finally an empty batch.
 */
const dirEntry = (name: string, children: FileSystemEntry[]): FileSystemDirectoryEntry => {
  const batches = [children.slice(0, 1), children.slice(1), [] as FileSystemEntry[]];
  return {
    isFile: false,
    isDirectory: true,
    name,
    createReader: () => {
      let call = 0;
      return {
        readEntries: (success: (entries: FileSystemEntry[]) => void) => {
          const batch = batches[call] ?? [];
          call += 1;
          success(batch);
        },
      } as unknown as FileSystemDirectoryReader;
    },
  } as unknown as FileSystemDirectoryEntry;
};

test('filesFromEntries flattens nested folders and prefixes relative paths', async () => {
  const entries: FileSystemEntry[] = [
    fileEntry('top.txt'),
    dirEntry('photos', [
      fileEntry('a.jpg'),
      dirEntry('2024', [fileEntry('b.jpg'), fileEntry('c.jpg')]),
    ]),
  ];

  const files = await filesFromEntries(entries);
  const names = files.map((f) => f.name).sort();

  assert.deepEqual(names, ['photos/2024/b.jpg', 'photos/2024/c.jpg', 'photos/a.jpg', 'top.txt']);
});

test('filesFromEntries reads directory entries in batches until empty', async () => {
  const entries: FileSystemEntry[] = [
    dirEntry('docs', [fileEntry('one.txt'), fileEntry('two.txt')]),
  ];

  const files = await filesFromEntries(entries);
  assert.equal(files.length, 2);
});

test('filesFromEntries respects the maxFiles cap', async () => {
  const entries: FileSystemEntry[] = [
    dirEntry('many', [fileEntry('a.txt'), fileEntry('b.txt')]),
    fileEntry('c.txt'),
  ];

  const files = await filesFromEntries(entries, 2);
  assert.equal(files.length, 2);
});
