import { describe, it, expect } from 'vitest';
import { stitchSegments } from './stitch';
import { planChunks } from './chunking';
import type { Segment } from '../types';

const SR = 16000;

describe('stitchSegments', () => {
  it('passes a single chunk through unchanged (offset 0)', () => {
    const plan = planChunks(10 * SR, { sampleRate: SR });
    const segs: Segment[] = [
      { start: 0, end: 2, text: 'hello' },
      { start: 2, end: 4, text: 'world' },
    ];
    const out = stitchSegments([segs], plan);
    expect(out.map((s) => s.text)).toEqual(['hello', 'world']);
    expect(out[0]).toMatchObject({ start: 0, end: 2 });
  });

  it('offsets chunk-local times into absolute time', () => {
    const plan = planChunks(60 * SR, { windowSec: 28, overlapSec: 2, sampleRate: SR });
    expect(plan.length).toBeGreaterThanOrEqual(2);
    const perChunk: Segment[][] = plan.map((_, i) => [{ start: 1, end: 2, text: `c${i}` }]);
    const out = stitchSegments(perChunk, plan);

    expect(out.find((s) => s.text === 'c0')!.start).toBeCloseTo(1);
    const c1 = plan[1]!;
    expect(out.find((s) => s.text === 'c1')!.start).toBeCloseTo(c1.startSec + 1);
  });

  it('keeps a word duplicated across the overlap only once', () => {
    const plan = planChunks(60 * SR, { windowSec: 28, overlapSec: 2, sampleRate: SR });
    const c0 = plan[0]!;
    const c1 = plan[1]!;
    const seamAbs = c1.startSec + 0.5; // inside the 2s overlap, below the mid cut

    const perChunk: Segment[][] = plan.map(() => []);
    perChunk[0] = [{ start: seamAbs - c0.startSec - 0.25, end: seamAbs - c0.startSec + 0.25, text: 'seam' }];
    perChunk[1] = [{ start: seamAbs - c1.startSec - 0.25, end: seamAbs - c1.startSec + 0.25, text: 'seam' }];

    const out = stitchSegments(perChunk, plan, { overlapSec: 2 });
    expect(out.filter((s) => s.text === 'seam')).toHaveLength(1);
  });

  it('produces monotonic, non-overlapping output', () => {
    const plan = planChunks(10 * SR, { sampleRate: SR });
    const segs: Segment[] = [
      { start: 0, end: 3, text: 'a' },
      { start: 2.5, end: 5, text: 'b' },
    ];
    const out = stitchSegments([segs], plan);
    for (let i = 1; i < out.length; i++) {
      expect(out[i]!.start).toBeGreaterThanOrEqual(out[i - 1]!.start);
      expect(out[i - 1]!.end).toBeLessThanOrEqual(out[i]!.start + 1e-9);
    }
  });

  it('tolerates missing/empty chunk entries', () => {
    const plan = planChunks(60 * SR, { sampleRate: SR });
    const out = stitchSegments([], plan);
    expect(out).toEqual([]);
  });
});
