import { describe, expect, it } from 'vitest';
import { levenshteinDistance } from '.';

describe('levenshteinDistance', () => {
  it('calculate edit distance between two strings', () => {
    // just one substitution I at the beginning
    expect(levenshteinDistance('islander', 'slander')).toBe(1);

    // substitution M->K, T->M and add an A to the end
    expect(levenshteinDistance('mart', 'karma')).toBe(3);

    // substitution K->S, E->I and insert G at the end
    expect(levenshteinDistance('kitten', 'sitting')).toBe(3);

    // should add 4 letters FOOT at the beginning
    expect(levenshteinDistance('ball', 'football')).toBe(4);

    // should delete 4 letters FOOT at the beginning
    expect(levenshteinDistance('football', 'foot')).toBe(4);

    // needs to substitute the first 5 chars INTEN->EXECU
    expect(levenshteinDistance('intention', 'execution')).toBe(5);
  });

  it('handle empty strings', () => {
    expect(levenshteinDistance('', '')).toBe(0);
    expect(levenshteinDistance('a', '')).toBe(1);
    expect(levenshteinDistance('', 'a')).toBe(1);
    expect(levenshteinDistance('abc', '')).toBe(3);
    expect(levenshteinDistance('', 'abc')).toBe(3);
  });

  it('is symmetric', () => {
    expect(levenshteinDistance('kitten', 'sitting')).toBe(levenshteinDistance('sitting', 'kitten'));
    expect(levenshteinDistance('football', 'foot')).toBe(levenshteinDistance('foot', 'football'));
  });

  it('counts UTF-16 code units (surrogate pairs count as two)', () => {
    expect(levenshteinDistance('😀', '')).toBe(2); // surrogate pair = 2 code units
    expect(levenshteinDistance('a😀b', 'a😀b')).toBe(0);
    expect(levenshteinDistance('café', 'cafe')).toBe(1);
  });
});
