#!/usr/bin/env python3
"""Build a deterministic pause-tightening recut spec from Whisper words.

Every source word remains inside exactly one interval. Long inter-phrase pauses
are reduced by trimming around word boundaries; spoken audio is never
time-stretched.
"""
from __future__ import annotations

import argparse
import json
from pathlib import Path


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("words_json")
    parser.add_argument("output")
    parser.add_argument("--pad", type=float, default=0.06)
    parser.add_argument("--tail", type=float, default=1.8)
    parser.add_argument("--source-index", type=int, default=0)
    args = parser.parse_args()

    transcript_path = Path(args.words_json).resolve()
    transcript = json.loads(transcript_path.read_text(encoding="utf-8"))
    words = transcript["words"]
    if not words:
        raise SystemExit("Transcript has no words")

    grouped: dict[int, list[dict]] = {}
    for word in words:
        grouped.setdefault(int(word["segment_id"]), []).append(word)

    groups = [grouped[key] for key in sorted(grouped)]
    intervals: list[dict] = []
    cursor = 0.0
    for index, group in enumerate(groups):
        first_start = float(group[0]["start"])
        last_end = float(group[-1]["end"])
        previous_end = float(groups[index - 1][-1]["end"]) if index else 0.0
        next_start = float(groups[index + 1][0]["start"]) if index + 1 < len(groups) else float(transcript.get("duration") or last_end)

        source_in = max(previous_end, first_start - args.pad)
        source_out = min(next_start, last_end + args.pad)
        if source_out <= source_in:
            raise SystemExit(f"Invalid interval around segment {index}")

        duration = source_out - source_in
        intervals.append({
            "id": index,
            "source_index": args.source_index,
            "source_in": round(source_in, 6),
            "source_out": round(source_out, 6),
            "global_start": round(cursor, 6),
            "duration": round(duration, 6),
            "first_word_id": int(group[0]["id"]),
            "last_word_id": int(group[-1]["id"]),
        })
        cursor += duration

    expected_duration = cursor + args.tail
    payload = {
        "version": "3.2-pause-safe",
        "speech_source_index": args.source_index,
        "speech_segments": intervals,
        "visual_segments": [],
        "tail_after_speech": round(args.tail, 6),
        "expected_duration": round(expected_duration, 6),
        "integrity": {
            "source_words": len(words),
            "kept_words": len(words),
            "excluded_words": 0,
        },
    }
    output = Path(args.output)
    output.parent.mkdir(parents=True, exist_ok=True)
    output.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    print(json.dumps({
        "output": str(output.resolve()),
        "segments": len(intervals),
        "words": len(words),
        "expected_duration": round(expected_duration, 6),
        "status": "ok",
    }, ensure_ascii=False))


if __name__ == "__main__":
    main()
