import { describe, it, expect } from 'vitest';
import { filterMatches, categoriesForSystem, type FilterDef, type Entry } from './registry';

const eqType: FilterDef = {
  key: 'type', label: 'Type', kind: 'eq',
  get: (e) => e.type as string, options: () => [],
};
const crGte: FilterDef = {
  key: 'crMin', label: 'Min CR', kind: 'gte',
  get: (e) => e.cr as number, options: () => [],
};
const traitEq: FilterDef = {
  key: 'trait', label: 'Trait', kind: 'eq',
  get: (e) => e.trait as string[], options: () => [],
};

describe('filterMatches', () => {
  it('eq matches exact string', () => {
    expect(filterMatches(eqType, { name: 'x', type: 'dragon' } as Entry, 'dragon')).toBe(true);
    expect(filterMatches(eqType, { name: 'x', type: 'goblin' } as Entry, 'dragon')).toBe(false);
  });
  it('gte compares numerically', () => {
    expect(filterMatches(crGte, { name: 'x', cr: 10 } as Entry, '5')).toBe(true);
    expect(filterMatches(crGte, { name: 'x', cr: 2 } as Entry, '5')).toBe(false);
  });
  it('array fields match by membership', () => {
    expect(filterMatches(traitEq, { name: 'x', trait: ['Fire', 'Evocation'] } as Entry, 'Fire')).toBe(true);
    expect(filterMatches(traitEq, { name: 'x', trait: ['Cold'] } as Entry, 'Fire')).toBe(false);
  });
});

describe('category registry', () => {
  it('exposes 5e and pf2e categories', () => {
    const fivee = categoriesForSystem('5e').map((c) => c.label);
    const pf2e = categoriesForSystem('pf2e').map((c) => c.label);
    expect(fivee).toContain('Bestiary');
    expect(fivee).toContain('Spells');
    expect(fivee).toContain('Feats');
    expect(pf2e).toContain('Bestiary');
    expect(pf2e).toContain('Spells');
    expect(pf2e.length).toBeGreaterThan(8);
  });
  it('every category has a unique id', () => {
    const all = [...categoriesForSystem('5e'), ...categoriesForSystem('pf2e')];
    const ids = all.map((c) => c.id);
    expect(new Set(ids).size).toBe(ids.length);
  });
});
