#!/bin/sh

set -eu
export LC_ALL=C
export TZ=UTC

script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
project_root=$(CDPATH= cd -- "$script_dir/.." && pwd -P)
output_dir="$project_root/tests/fixtures/generated"
force=false

if [ "${1:-}" = "--force" ]; then
  force=true
  shift
fi

if [ "$#" -ne 0 ]; then
  echo "Usage: scripts/generate-fixtures.sh [--force]" >&2
  exit 2
fi

for command_name in ffmpeg ffprobe head sha256sum mktemp; do
  if ! command -v "$command_name" >/dev/null 2>&1; then
    echo "Required development command is unavailable: $command_name" >&2
    exit 1
  fi
done

fixture_names="
pattern-av.mp4
compatible-a.mp4
compatible-b.mp4
different-dimensions.mp4
tone.wav
tone.mp3
tone.flac
pattern.webm
subtitle.srt
subtitle.vtt
subtitle.ass
metadata.mp4
chapters.mp4
attached-cover.mp3
truncated.mp4
SHA256SUMS
"

mkdir -p "$output_dir"
if [ -L "$output_dir" ] || [ ! -d "$output_dir" ]; then
  echo "Fixture output must be a real directory: $output_dir" >&2
  exit 1
fi
canonical_output_dir=$(CDPATH= cd -- "$output_dir" && pwd -P)
if [ "$canonical_output_dir" != "$project_root/tests/fixtures/generated" ]; then
  echo "Fixture output resolves outside the expected project path." >&2
  exit 1
fi
for fixture_name in $fixture_names; do
  fixture_path="$output_dir/$fixture_name"
  if [ -e "$fixture_path" ] && [ "$force" != true ]; then
    echo "Fixture already exists: $fixture_path" >&2
    echo "Pass --force to replace only the known generated fixture set." >&2
    exit 1
  fi
done

if [ "$force" = true ]; then
  for fixture_name in $fixture_names; do
    rm -f -- "$output_dir/$fixture_name"
  done
fi

temporary_dir=$(mktemp -d "/tmp/av-tools-fixtures.XXXXXX")
case "$temporary_dir" in
  /tmp/av-tools-fixtures.*) ;;
  *)
    echo "Refusing unexpected temporary path: $temporary_dir" >&2
    exit 1
    ;;
esac
trap 'rm -rf -- "$temporary_dir"' EXIT HUP INT TERM

run_ffmpeg() {
  ffmpeg \
    -hide_banner \
    -loglevel error \
    -y \
    -fflags +bitexact \
    -filter_threads 1 \
    -filter_complex_threads 1 \
    "$@"
}

run_ffmpeg \
  -f lavfi -i "testsrc2=size=160x90:rate=12" \
  -f lavfi -i "sine=frequency=440:sample_rate=16000" \
  -t 2 -shortest \
  -map 0:v:0 -map 1:a:0 \
  -c:v libx264 -preset ultrafast -crf 35 -pix_fmt yuv420p -g 12 -threads 1 \
  -c:a aac -b:a 32k -ar 16000 -ac 1 \
  -flags:v +bitexact -flags:a +bitexact \
  -metadata title="Generated AV fixture" \
  -metadata creation_time="2020-01-01T00:00:00Z" \
  -movflags +faststart \
  "$output_dir/pattern-av.mp4"

run_ffmpeg \
  -f lavfi -i "color=c=red:size=128x72:rate=10" \
  -f lavfi -i "sine=frequency=330:sample_rate=16000" \
  -t 1 -shortest \
  -map 0:v:0 -map 1:a:0 \
  -c:v libx264 -preset ultrafast -crf 35 -pix_fmt yuv420p -g 10 -threads 1 \
  -c:a aac -b:a 32k -ar 16000 -ac 1 \
  -flags:v +bitexact -flags:a +bitexact \
  -metadata creation_time="2020-01-01T00:00:00Z" \
  -movflags +faststart \
  "$output_dir/compatible-a.mp4"

run_ffmpeg \
  -f lavfi -i "color=c=blue:size=128x72:rate=10" \
  -f lavfi -i "sine=frequency=550:sample_rate=16000" \
  -t 1 -shortest \
  -map 0:v:0 -map 1:a:0 \
  -c:v libx264 -preset ultrafast -crf 35 -pix_fmt yuv420p -g 10 -threads 1 \
  -c:a aac -b:a 32k -ar 16000 -ac 1 \
  -flags:v +bitexact -flags:a +bitexact \
  -metadata creation_time="2020-01-01T00:00:00Z" \
  -movflags +faststart \
  "$output_dir/compatible-b.mp4"

run_ffmpeg \
  -f lavfi -i "testsrc2=size=96x96:rate=10" \
  -f lavfi -i "sine=frequency=660:sample_rate=16000" \
  -t 1 -shortest \
  -map 0:v:0 -map 1:a:0 \
  -c:v libx264 -preset ultrafast -crf 35 -pix_fmt yuv420p -g 10 -threads 1 \
  -c:a aac -b:a 32k -ar 16000 -ac 1 \
  -flags:v +bitexact -flags:a +bitexact \
  -metadata creation_time="2020-01-01T00:00:00Z" \
  -movflags +faststart \
  "$output_dir/different-dimensions.mp4"

run_ffmpeg \
  -f lavfi -i "sine=frequency=440:sample_rate=16000:duration=1" \
  -c:a pcm_s16le -flags:a +bitexact \
  -metadata title="Generated tone" \
  "$output_dir/tone.wav"

run_ffmpeg \
  -f lavfi -i "sine=frequency=440:sample_rate=16000:duration=1" \
  -c:a libmp3lame -b:a 32k -ar 16000 -ac 1 -flags:a +bitexact \
  -id3v2_version 3 -write_xing 0 \
  -metadata title="Generated tone" \
  "$output_dir/tone.mp3"

run_ffmpeg \
  -f lavfi -i "sine=frequency=440:sample_rate=16000:duration=1" \
  -c:a flac -compression_level 5 -flags:a +bitexact \
  -metadata title="Generated tone" \
  "$output_dir/tone.flac"

run_ffmpeg \
  -f lavfi -i "testsrc2=size=128x72:rate=10" \
  -f lavfi -i "sine=frequency=440:sample_rate=16000" \
  -t 1 -shortest \
  -map 0:v:0 -map 1:a:0 \
  -c:v libvpx -deadline good -cpu-used 8 -crf 50 -b:v 80k -threads 1 \
  -c:a libvorbis -b:a 32k -ar 16000 -ac 1 \
  -flags:v +bitexact -flags:a +bitexact \
  -metadata title="Generated WebM fixture" \
  -fflags +bitexact \
  "$output_dir/pattern.webm"

printf '%s\n' \
  '1' \
  '00:00:00,100 --> 00:00:00,700' \
  'Generated subtitle' \
  >"$output_dir/subtitle.srt"

printf '%s\n' \
  'WEBVTT' \
  '' \
  '00:00:00.100 --> 00:00:00.700' \
  'Generated subtitle' \
  >"$output_dir/subtitle.vtt"

printf '%s\n' \
  '[Script Info]' \
  'ScriptType: v4.00+' \
  'PlayResX: 128' \
  'PlayResY: 72' \
  '' \
  '[V4+ Styles]' \
  'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding' \
  'Style: Default,sans-serif,12,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,1,0,2,8,8,8,1' \
  '' \
  '[Events]' \
  'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text' \
  'Dialogue: 0,0:00:00.10,0:00:00.70,Default,,0,0,0,,Generated subtitle' \
  >"$output_dir/subtitle.ass"

run_ffmpeg \
  -i "$output_dir/compatible-a.mp4" \
  -map 0 -c copy \
  -metadata title="Metadata fixture" \
  -metadata artist="add ideas test generator" \
  -metadata comment="Local generated media" \
  -metadata creation_time="2020-01-01T00:00:00Z" \
  "$output_dir/metadata.mp4"

printf '%s\n' \
  ';FFMETADATA1' \
  'title=Chapter fixture' \
  '[CHAPTER]' \
  'TIMEBASE=1/1000' \
  'START=0' \
  'END=500' \
  'title=First' \
  '[CHAPTER]' \
  'TIMEBASE=1/1000' \
  'START=500' \
  'END=1000' \
  'title=Second' \
  >"$temporary_dir/chapters.ffmeta"

run_ffmpeg \
  -i "$output_dir/compatible-b.mp4" \
  -i "$temporary_dir/chapters.ffmeta" \
  -map 0 -map_metadata 1 -map_chapters 1 -c copy \
  -metadata creation_time="2020-01-01T00:00:00Z" \
  "$output_dir/chapters.mp4"

run_ffmpeg \
  -f lavfi -i "color=c=yellow:size=32x32:rate=1" \
  -frames:v 1 -c:v png -threads 1 -flags:v +bitexact \
  "$temporary_dir/cover.png"

run_ffmpeg \
  -f lavfi -i "sine=frequency=440:sample_rate=16000:duration=1" \
  -i "$temporary_dir/cover.png" \
  -map 0:a:0 -map 1:v:0 \
  -c:a libmp3lame -b:a 32k -ar 16000 -ac 1 \
  -c:v png -threads 1 -disposition:v:0 attached_pic \
  -id3v2_version 3 -write_xing 0 \
  -metadata title="Attached cover fixture" \
  -metadata:s:v:0 title="Generated cover" \
  -metadata:s:v:0 comment="Cover (front)" \
  "$output_dir/attached-cover.mp3"

head -c 128 "$output_dir/compatible-a.mp4" >"$output_dir/truncated.mp4"

for media_name in \
  attached-cover.mp3 \
  chapters.mp4 \
  compatible-a.mp4 \
  compatible-b.mp4 \
  different-dimensions.mp4 \
  metadata.mp4 \
  pattern-av.mp4 \
  pattern.webm \
  tone.flac \
  tone.mp3 \
  tone.wav
do
  ffprobe \
    -v error \
    -show_entries format=format_name,duration:stream=index,codec_name,codec_type \
    -of json \
    "$output_dir/$media_name" \
    >/dev/null
done

truncated_streams=$(
  ffprobe \
    -v error \
    -show_entries stream=index \
    -of csv=p=0 \
    "$output_dir/truncated.mp4"
)
if [ -n "$truncated_streams" ]; then
  echo "Truncated fixture unexpectedly contains a usable stream." >&2
  exit 1
fi

(
  cd "$output_dir"
  sha256sum \
    attached-cover.mp3 \
    chapters.mp4 \
    compatible-a.mp4 \
    compatible-b.mp4 \
    different-dimensions.mp4 \
    metadata.mp4 \
    pattern-av.mp4 \
    pattern.webm \
    subtitle.ass \
    subtitle.srt \
    subtitle.vtt \
    tone.flac \
    tone.mp3 \
    tone.wav \
    truncated.mp4 \
    >SHA256SUMS
)

for fixture_name in $fixture_names; do
  chmod 0644 "$output_dir/$fixture_name"
done

echo "Generated fixtures in $output_dir"
ffmpeg -version | sed -n '1p'
(
  cd "$output_dir"
  sha256sum -c SHA256SUMS
)
