import { projectFilePath } from '@learnitive/project-storage';
import { describe, expect, it } from 'vitest';
import {
  citedEvidenceIds,
  projectRagLexicalScore,
  rankProjectRagCandidates,
  sanitizeEvidenceCitations,
  scientificTokens,
} from '../index';

const candidate = (overrides: Record<string, unknown> = {}) => ({
  key: 'a', file: projectFilePath('main.tex'), line: 1, from: 0, to: 10, kind: 'prose' as const,
  text: 'AdamW uses beta_2 = 0.999 and learning rate 10^-4.', ...overrides,
});

describe('project rag', () => {
  it('keeps scientific exact terms searchable', () => {
    expect(scientificTokens('AdamW beta_2 10^-4 ResNet-50')).toEqual(expect.arrayContaining(['adamw', 'beta_2', '10^-4', 'resnet-50']));
    expect(projectRagLexicalScore('beta_2 10^-4', candidate().text)).toBeGreaterThan(0.6);
  });

  it('keeps deterministic exact evidence competitive with semantic evidence', () => {
    const ranked = rankProjectRagCandidates([
      candidate({ key: 'semantic', from: 20, to: 30, semanticScore: 0.91, lexicalScore: 0.1 }),
      candidate({ key: 'exact', deterministicScore: 1, lexicalScore: 1 }),
    ], 2);
    expect(ranked[0]?.key).toBe('exact');
  });

  it('accepts only trusted source ids', () => {
    const allowed = new Set(['S1', 'S2']);
    expect(citedEvidenceIds('Claim [S1] fake [S99] [S2].', allowed)).toEqual(['S1', 'S2']);
    expect(sanitizeEvidenceCitations('Claim [S1] fake [S99].', allowed)).toBe('Claim [S1] fake [unsupported source].');
  });
});
