import { describe, expect, it } from 'bun:test';
import { toParagraphs } from './transcribe';
import type { WhisperSegment } from './transcribe';

// Whisper's own shape: leading space on every segment, times in seconds.
const seg = (text: string, start: number, end: number, extra: Partial<WhisperSegment> = {}): WhisperSegment => ({
  text,
  start,
  end,
  ...extra,
});

describe('toParagraphs', () => {
  it('joins segments spoken without a real pause into one paragraph', () => {
    const out = toParagraphs([seg(' I went to the shop.', 0, 2), seg(' It was closed.', 2.2, 4)]);
    expect(out).toBe('I went to the shop. It was closed.');
  });

  it('starts a new paragraph after a long silence', () => {
    const out = toParagraphs([seg(' First thought.', 0, 2), seg(' Second thought.', 5, 7)]);
    expect(out).toBe('First thought.\n\nSecond thought.');
  });

  it('does not break on a breath-length pause', () => {
    const out = toParagraphs([seg(' Hang on,', 0, 1), seg(' let me think.', 1.5, 3)]);
    expect(out).toBe('Hang on, let me think.');
  });

  // The lone "." lines in the old response_format=text output came from segments like this.
  it('attaches stranded punctuation without a space in front of it', () => {
    const out = toParagraphs([seg(' See you tomorrow morning', 0, 2), seg(' .', 2.1, 2.2)]);
    expect(out).toBe('See you tomorrow morning.');
  });

  it('drops segments that are probably silence decoded with low confidence', () => {
    const out = toParagraphs([
      seg(' Real speech here.', 0, 2),
      seg(' Thanks for watching!', 2.1, 3, { no_speech_prob: 0.95, avg_logprob: -1.8 }),
      seg(' More real speech.', 3.1, 5),
    ]);
    expect(out).toBe('Real speech here. More real speech.');
  });

  it('keeps a confident segment even when it looks like silence', () => {
    const out = toParagraphs([seg(' Definitely said.', 0, 2, { no_speech_prob: 0.95, avg_logprob: -0.2 })]);
    expect(out).toBe('Definitely said.');
  });

  it('keeps segments that report neither probability', () => {
    const out = toParagraphs([seg(' No metadata at all.', 0, 2)]);
    expect(out).toBe('No metadata at all.');
  });

  it('measures the pause from the last kept segment, not the dropped one', () => {
    const out = toParagraphs([
      seg(' Before.', 0, 2),
      seg(' Hallucinated.', 2.1, 9, { no_speech_prob: 0.9, avg_logprob: -2 }),
      seg(' After.', 9.1, 11),
    ]);
    // The gap that matters is 2 -> 9.1, so these are separate thoughts.
    expect(out).toBe('Before.\n\nAfter.');
  });

  it('collapses internal whitespace and ignores empty segments', () => {
    const out = toParagraphs([seg('  Too   many\n spaces. ', 0, 2), seg('   ', 2.1, 2.2)]);
    expect(out).toBe('Too many spaces.');
  });

  it('returns an empty string when every segment is filtered out', () => {
    expect(toParagraphs([])).toBe('');
    expect(toParagraphs([seg('  ', 0, 1)])).toBe('');
  });

  it('falls back to no break when segments carry no timings', () => {
    const out = toParagraphs([{ text: ' One.' }, { text: ' Two.' }]);
    expect(out).toBe('One. Two.');
  });
});
