import { describe, it, expect } from 'vitest';
import { isContentDuplicate, isExactDuplicate, findClosestMatch } from '../dedup.js';

describe('isContentDuplicate', () => {
  const baseEmbedding = [1, 0, 0];
  const similarEmbedding = [0.99, 0.1, 0]; // very similar to base
  const differentEmbedding = [0, 1, 0]; // orthogonal

  it('detects near-duplicate above threshold', () => {
    expect(isContentDuplicate(baseEmbedding, [similarEmbedding], 0.9)).toBe(true);
  });

  it('rejects non-duplicate below threshold', () => {
    expect(isContentDuplicate(baseEmbedding, [differentEmbedding], 0.9)).toBe(false);
  });

  it('returns false for empty existing embeddings', () => {
    expect(isContentDuplicate(baseEmbedding, [], 0.9)).toBe(false);
  });

  it('skips embeddings with mismatched dimensions', () => {
    expect(isContentDuplicate([1, 0], [[1, 0, 0]], 0.9)).toBe(false);
  });

  it('uses default threshold of 0.90', () => {
    expect(isContentDuplicate(baseEmbedding, [similarEmbedding])).toBe(true);
  });
});

describe('isExactDuplicate', () => {
  it('detects exact match', () => {
    expect(isExactDuplicate('Hello World', 'Hello World')).toBe(true);
  });

  it('is case-insensitive', () => {
    expect(isExactDuplicate('Hello', 'hello')).toBe(true);
  });

  it('trims whitespace', () => {
    expect(isExactDuplicate('  hello  ', 'hello')).toBe(true);
  });

  it('rejects different content', () => {
    expect(isExactDuplicate('Hello', 'World')).toBe(false);
  });
});

describe('findClosestMatch', () => {
  it('finds the closest embedding', () => {
    const result = findClosestMatch(
      [1, 0, 0],
      [
        [0, 1, 0],
        [0.9, 0.1, 0],
        [0, 0, 1],
      ]
    );
    expect(result).not.toBeNull();
    expect(result!.index).toBe(1);
    expect(result!.score).toBeGreaterThan(0.9);
  });

  it('returns null for empty embeddings', () => {
    expect(findClosestMatch([1, 0], [])).toBeNull();
  });

  it('returns null when no embedding exceeds minScore', () => {
    expect(findClosestMatch([1, 0, 0], [[0, 1, 0]], 0.99)).toBeNull();
  });
});
