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

// The module evaluates atomWithStorage(..., { getOnInit: true }), which reads
// localStorage at load time. node has none, so install a no-op mock, then import
// dynamically (a static import would hoist above the mock and evaluate too early).
(globalThis as { localStorage?: unknown }).localStorage = {
  getItem: () => null,
  setItem: () => undefined,
  removeItem: () => undefined,
};

const { addRecentGif } = await import('./recentGifs');

const gif = (url: string, width = 100, height = 100) => ({ url, width, height });

test('addRecentGif prepends a new gif', () => {
  const out = addRecentGif([gif('a'), gif('b')], gif('c'));
  assert.deepEqual(
    out.map((g) => g.url),
    ['c', 'a', 'b'],
  );
});

test('addRecentGif de-dupes by url, moving the entry to the front', () => {
  const out = addRecentGif([gif('a'), gif('b'), gif('c')], gif('b'));
  assert.deepEqual(
    out.map((g) => g.url),
    ['b', 'a', 'c'],
  );
});

test('addRecentGif ignores an empty url', () => {
  assert.deepEqual(addRecentGif([gif('a')], gif('')), [gif('a')]);
});

test('addRecentGif caps the list at 16, dropping the oldest', () => {
  const sixteen = Array.from({ length: 16 }, (_, i) => gif(`u${i}`));
  const out = addRecentGif(sixteen, gif('new'));
  assert.equal(out.length, 16);
  assert.equal(out[0].url, 'new');
  assert.equal(
    out.some((g) => g.url === 'u15'),
    false,
  );
});

test('addRecentGif does not mutate its input', () => {
  const input = [gif('a'), gif('b')];
  const before = input.map((g) => g.url);
  addRecentGif(input, gif('c'));
  assert.deepEqual(
    input.map((g) => g.url),
    before,
  );
});
