import type { Segment } from '../types';
import type { ChunkPlanItem } from './chunking';

export interface StitchOptions {
  /** Overlap (seconds) between adjacent chunks; should match planChunks. */
  overlapSec?: number;
}

/**
 * Merge per-chunk, CHUNK-LOCAL segment lists into one absolute-time transcript.
 *
 * `perChunk[i]` holds the segments engine returned for chunk `i`, with times
 * relative to that chunk's start. We offset each by `plan[i].startSec`, then at
 * every seam choose a cut point in the middle of the overlap and assign each
 * segment to a chunk by its midpoint: the earlier chunk owns everything before
 * the cut, the later chunk everything after. Because Whisper truncates and
 * occasionally hallucinates at a window edge, a mid-overlap cut drops the
 * duplicated/garbled boundary copy and keeps the clean one. Finally we sort and
 * clamp so the output is monotonic and non-overlapping (nice for the editor).
 */
export function stitchSegments(
  perChunk: Segment[][],
  plan: ChunkPlanItem[],
  opts: StitchOptions = {},
): Segment[] {
  const overlapSec = opts.overlapSec ?? 2;
  const out: Segment[] = [];

  for (let i = 0; i < plan.length; i++) {
    const chunk = plan[i];
    const segs = perChunk[i];
    if (!chunk || !segs) continue;

    const offset = chunk.startSec;
    // Below the cut shared with the previous chunk → that chunk already owns it.
    const lowerCut = i > 0 ? chunk.startSec + overlapSec / 2 : -Infinity;
    // At/after the cut shared with the next chunk → the next chunk will own it.
    const next = plan[i + 1];
    const upperCut = next ? next.startSec + overlapSec / 2 : Infinity;

    for (const s of segs) {
      const start = s.start + offset;
      const end = s.end + offset;
      const mid = (start + end) / 2;
      if (mid < lowerCut || mid >= upperCut) continue;
      out.push({ ...s, start, end });
    }
  }

  out.sort((a, b) => a.start - b.start || a.end - b.end);

  // Clamp so each segment ends no later than the next one starts.
  for (let i = 0; i < out.length - 1; i++) {
    const cur = out[i]!;
    const nxt = out[i + 1]!;
    if (cur.end > nxt.start) cur.end = nxt.start;
  }
  return out;
}
