import { describe, it, expect } from 'vitest';
import { lexicalRank } from './lexical';

describe('lexicalRank', () => {
  it('returns [] for an empty query', () => {
    const rows = [{ id: 'a', text: 'hello world' }];
    expect(lexicalRank(rows, '')).toEqual([]);
    expect(lexicalRank(rows, '   ')).toEqual([]);
    expect(lexicalRank(rows, '!!! ???')).toEqual([]);
  });

  it('returns [] when no row matches', () => {
    const rows = [
      { id: 'a', text: 'the quick brown fox' },
      { id: 'b', text: 'lazy dog' },
    ];
    expect(lexicalRank(rows, 'elephant')).toEqual([]);
  });

  it('scores by total term-occurrence count', () => {
    const rows = [
      { id: 'a', text: 'cat cat cat' },
      { id: 'b', text: 'cat dog' },
    ];
    const out = lexicalRank(rows, 'cat');
    expect(out).toEqual([
      { id: 'a', score: 3 },
      { id: 'b', score: 1 },
    ]);
  });

  it('is case-insensitive and tokenizes on non-word chars', () => {
    const rows = [{ id: 'a', text: 'Neural-Networks, neural networks!' }];
    // "neural" appears twice, "networks" appears twice => 4.
    expect(lexicalRank(rows, 'Neural networks')).toEqual([{ id: 'a', score: 4 }]);
  });

  it('sums distinct query terms and drops zero-score rows', () => {
    const rows = [
      { id: 'a', text: 'gradient descent and gradient ascent' }, // gradient x2
      { id: 'b', text: 'gradient boosting' }, // gradient x1
      { id: 'c', text: 'random forest' }, // 0 -> dropped
    ];
    const out = lexicalRank(rows, 'gradient descent');
    // a: gradient(2)+descent(1)=3 ; b: gradient(1)=1 ; c dropped
    expect(out).toEqual([
      { id: 'a', score: 3 },
      { id: 'b', score: 1 },
    ]);
  });

  it('sorts by score descending', () => {
    const rows = [
      { id: 'low', text: 'alpha' },
      { id: 'high', text: 'alpha alpha alpha' },
      { id: 'mid', text: 'alpha alpha' },
    ];
    expect(lexicalRank(rows, 'alpha').map((r) => r.id)).toEqual(['high', 'mid', 'low']);
  });

  it('skips rows with empty text', () => {
    const rows = [
      { id: 'empty', text: '' },
      { id: 'a', text: 'match match' },
    ];
    expect(lexicalRank(rows, 'match')).toEqual([{ id: 'a', score: 2 }]);
  });
});
