import { test, expect } from 'bun:test';
import { groupTasksByCategory, type TaskSummary } from './useTasks';

const task = (name: string, category: string | null): TaskSummary => ({
  id: 0,
  dirName: name.toLowerCase().replace(/\s+/g, '-'),
  name,
  description: '',
  scope: '',
  category,
  triggers: [{ type: 'directory' }],
  mode: 'script',
  userId: null,
});

const shape = (tasks: TaskSummary[], order: string[]) =>
  groupTasksByCategory(tasks, order).map((g) => `${g.category}(${g.tasks.length})`);

// The point of the grouping: categories.yaml is a sort key, never a source of menu entries. A
// category listed there with nothing in it must not render an empty submenu.
test('categories with no matching tasks do not appear', () => {
  const order = ['Video', 'Photos', 'Audio', 'Documents', 'Cleanup'];
  const groups = groupTasksByCategory([task('Convert Video', 'Video'), task('Tag Album', 'Audio')], order);

  expect(groups.map((g) => g.category)).toEqual(['Video', 'Audio']);
  expect(groups.every((g) => g.tasks.length > 0)).toBe(true);
});

test('an empty task list produces no groups at all', () => {
  expect(groupTasksByCategory([], ['Video', 'Audio'])).toEqual([]);
});

test('order follows categories.yaml', () => {
  const tasks = [task('A', 'Audio'), task('V', 'Video'), task('C', 'Cleanup')];
  expect(shape(tasks, ['Video', 'Audio', 'Cleanup'])).toEqual(['Video(1)', 'Audio(1)', 'Cleanup(1)']);
  expect(shape(tasks, ['Cleanup', 'Audio', 'Video'])).toEqual(['Cleanup(1)', 'Audio(1)', 'Video(1)']);
});

test('a category missing from the file still renders, after the listed ones', () => {
  const tasks = [task('Crop', 'Photos'), task('V', 'Video')];
  expect(shape(tasks, ['Video'])).toEqual(['Video(1)', 'Photos(1)']);
});

test('uncategorized tasks fall into Other, which sorts last', () => {
  const tasks = [task('Mystery', null), task('Blank', '  '), task('V', 'Video')];
  expect(shape(tasks, ['Video'])).toEqual(['Video(1)', 'Other(2)']);
});

test('with no order at all, categories sort alphabetically and Other stays last', () => {
  const tasks = [task('V', 'Video'), task('A', 'Audio'), task('M', null)];
  expect(shape(tasks, [])).toEqual(['Audio(1)', 'Video(1)', 'Other(1)']);
});

test('tasks within a group are sorted by display name', () => {
  const tasks = [task('Zebra', 'Video'), task('Alpha', 'Video')];
  expect(groupTasksByCategory(tasks, ['Video'])[0]!.tasks.map((t) => t.name)).toEqual(['Alpha', 'Zebra']);
});
