#!/usr/bin/env bash

set -euo pipefail

srt=false
chunk_minutes=30
usage() {
    echo "Usage: ${0##*/} [--srt] [--chunk-minutes 1..30] AUDIO_FILE"
    echo 'Transcribe audio using OPENROUTER_API_KEY; print the text to stdout.'
    echo '  --srt  Print SRT subtitles in short cues using word timestamps instead.'
    echo '  --chunk-minutes N  Maximum upload duration in minutes (default: 30).'
}
while [[ $# -gt 0 ]]; do
    case $1 in
        --srt) srt=true; shift ;;
        --chunk-minutes)
            if [[ ! ${2:-} =~ ^([1-9]|[12][0-9]|30)$ ]]; then
                echo '--chunk-minutes must be an integer between 1 and 30' >&2
                exit 1
            fi
            chunk_minutes=$2
            shift 2
            ;;
        -h|--help) usage; exit 0 ;;
        --) shift; break ;;
        -*) usage >&2; exit 1 ;;
        *) break ;;
    esac
done
if [[ $# != 1 ]]; then
    usage >&2
    exit 1
fi
if [[ ! -f $1 || ! -r $1 ]]; then
    echo "Cannot read audio file: $1" >&2
    exit 1
fi
export OPENROUTER_API_KEY
OPENROUTER_API_KEY="$(op read "op://API Keys/openrouter-mai-transcribe-2/credential")"
: "${OPENROUTER_API_KEY:?Set OPENROUTER_API_KEY first}"
dependencies=(ffmpeg curl jq base64 mktemp python3)
for tool in "${dependencies[@]}"; do
    command -v "$tool" >/dev/null || {
        echo "Missing dependency: $tool" >&2
        exit 1
    }
done

tmp=$(mktemp -d)
trap 'rm -rf -- "$tmp"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
script_dir=$(dirname -- "$(realpath -- "$0")")

# Decode once so duration, pause detection, and all cuts share a sample clock.
# This also works for inputs whose container omits or misreports the duration.
ffmpeg -nostdin -hide_banner -loglevel error -i "$(realpath -- "$1")" \
    -map 0:a:0 -ac 1 -ar 16000 -c:a pcm_s16le "$tmp/audio.wav"
python3 "$script_dir/chunks.py" plan "$tmp/audio.wav" "$chunk_minutes" >"$tmp/chunks.json"
count=$(jq 'length' "$tmp/chunks.json")
timestamps=$srt
if (( count > 1 )); then
    timestamps=true
    echo "Splitting audio into $count overlapping chunks (maximum $chunk_minutes minutes each)." >&2
fi

for ((i = 0; i < count; i++)); do
    read -r start duration < <(jq -r --argjson i "$i" \
        '.[$i] | "\(.start) \(.end - .start)"' "$tmp/chunks.json")
    if (( count > 1 )); then
        echo "Transcribing chunk $((i + 1))/$count (start ${start}s, duration ${duration}s)..." >&2
    fi
    ffmpeg -nostdin -hide_banner -loglevel error -y -ss "$start" -i "$tmp/audio.wav" \
        -t "$duration" -map 0:a:0 -ac 1 -ar 16000 -c:a libmp3lame -b:a 64k "$tmp/audio.mp3"

    # Keep large audio payloads out of shell arguments (which have a size limit).
    base64 <"$tmp/audio.mp3" | tr -d '\n\r' >"$tmp/audio.b64"
    jq -n --rawfile data "$tmp/audio.b64" --argjson timestamps "$timestamps" \
        '{model: "microsoft/mai-transcribe-2", input_audio: {data: $data, format: "mp3"}}
         + (if $timestamps then {response_format: "verbose_json", timestamp_granularities: ["segment", "word"]}
            else {} end)' \
        >"$tmp/request.json"

    curl --silent --show-error --fail-with-body \
        https://openrouter.ai/api/v1/audio/transcriptions \
        -H "Authorization: Bearer $OPENROUTER_API_KEY" \
        -H 'Content-Type: application/json' \
        --data-binary @"$tmp/request.json" -o "$tmp/response-$i.json" || {
        echo "Transcription failed for chunk $((i + 1))/$count." >&2
        if [[ -f $tmp/response-$i.json ]]; then
            cat "$tmp/response-$i.json" >&2
        fi
        exit 1
    }
    jq -e 'if .error then error("Transcription failed: " + (.error | tostring))
        elif (.text | type) == "string" then true
        else error("Transcription failed: missing text in response") end' \
        "$tmp/response-$i.json" >/dev/null
done

# Only emit a transcript after every chunk succeeds, including SRT conversion.
if (( count > 1 )); then
    format=()
    if "$srt"; then format+=(--srt); fi
    python3 "$script_dir/chunks.py" merge "$tmp/chunks.json" "${format[@]}"
elif "$srt"; then
    python3 "$script_dir/subtitles.py" "$tmp/response-0.json"
else
    jq -r .text "$tmp/response-0.json"
fi
