#!/bin/bash
# Usage: ./split-video.sh <video-datei>

set -o pipefail

if [[ $# -lt 1 ]]; then
  echo "Verwendung: $0 <video-datei>"
  exit 1
fi

input=$1

if [[ ! -f "$input" ]]; then
  echo "Fehler: Datei nicht gefunden: $input"
  exit 1
fi

for cmd in ffmpeg ffprobe awk stat; do
  if ! command -v "$cmd" >/dev/null 2>&1; then
    echo "Fehler: '$cmd' ist nicht installiert."
    exit 1
  fi
done

# Maximale Dateigröße abfragen
read -rp "Maximale Dateigröße pro Teil in MB: " max_mb

if ! [[ "$max_mb" =~ ^[0-9]+$ ]] || (( max_mb <= 10 )); then
  echo "Fehler: Bitte eine ganze Zahl größer als 10 eingeben."
  exit 1
fi

# Dezimale MB: 1 MB = 1.000.000 Bytes; Zielgröße 10 MB unter dem Maximum
target_bytes=$(((max_mb - 10) * 1000000))

# Dateiinformationen
input_dir=$(dirname -- "$input")
filename=$(basename -- "$input")
extension="${filename##*.}"

if [[ "$filename" == "$extension" ]]; then
  name="$filename"
  extension="mp4"
else
  name="${filename%.*}"
fi

input_size=$(stat -c%s -- "$input")

duration=$(ffprobe -v error \
  -show_entries format=duration \
  -of default=noprint_wrappers=1:nokey=1 \
  "$input")

if [[ -z "$duration" ]]; then
  echo "Fehler: Videodauer konnte nicht ermittelt werden."
  exit 1
fi

echo
echo "Eingabedatei:      $input"
echo "Dateigröße:        $((input_size / 1000000)) MB"
echo "Gesamtdauer:       ${duration} Sekunden"
echo "Maximale Größe:    ${max_mb} MB"
echo "Zielgröße:         $((target_bytes / 1000000)) MB"
echo

# Temporäres Arbeitsverzeichnis
tmpdir=$(mktemp -d) || exit 1
trap 'rm -rf -- "$tmpdir"' EXIT

# Initiale Schätzung anhand der durchschnittlichen Bitrate
chunk_duration=$(awk \
  -v d="$duration" \
  -v s="$input_size" \
  -v t="$target_bytes" \
  'BEGIN { printf "%.6f", d * t / s }')

start=0
part=1
total_part_duration=0

echo "Starte Aufteilung ..."
echo

while awk -v s="$start" -v d="$duration" \
  'BEGIN { exit !(s < d - 0.05) }'; do

  remaining=$(awk -v d="$duration" -v s="$start" \
    'BEGIN { printf "%.6f", d - s }')

  # Nicht über das Ende der Quelldatei hinausgehen
  if awk -v c="$chunk_duration" -v r="$remaining" \
    'BEGIN { exit !(c > r) }'; then
    chunk_duration="$remaining"
  fi

  output="${tmpdir}/Teil${part}.${extension}"
  accepted=false

  echo "Erstelle Teil $part ab ${start}s ..."

  # Mehrere Versuche, falls die Datei zu groß wird
  for attempt in {1..20}; do

    rm -f -- "$output"

    if ! ffmpeg -hide_banner -loglevel error -y \
      -ss "$start" \
      -i "$input" \
      -t "$chunk_duration" \
      -map 0 \
      -c copy \
      -avoid_negative_ts make_zero \
      "$output"; then

      echo "Fehler beim Erstellen von Teil $part."
      exit 1
    fi

    if [[ ! -s "$output" ]]; then
      echo "Fehler: Teil $part ist leer."
      exit 1
    fi

    actual_size=$(stat -c%s -- "$output")

    if (( actual_size <= target_bytes )); then
      accepted=true
      break
    fi

    echo "  Zu groß: $((actual_size / 1000000)) MB – verkleinere Schnittdauer."

    # Schnittdauer proportional reduzieren, mit zusätzlichem Puffer
    chunk_duration=$(awk \
      -v c="$chunk_duration" \
      -v s="$actual_size" \
      -v t="$target_bytes" \
      'BEGIN { printf "%.6f", c * t / s * 0.95 }')

    if ! awk -v c="$chunk_duration" \
      'BEGIN { exit !(c > 0.1) }'; then
      echo "Fehler: Schnittdauer ist zu klein. Abbruch."
      exit 1
    fi
  done

  if [[ "$accepted" != true ]]; then
    echo "Fehler: Teil $part konnte nicht auf die Zielgröße reduziert werden."
    echo "Möglicherweise ist bereits ein einzelner Keyframe-Bereich zu groß."
    exit 1
  fi

  # Tatsächliche Dauer des erzeugten Teils ermitteln
  part_duration=$(ffprobe -v error \
    -show_entries format=duration \
    -of default=noprint_wrappers=1:nokey=1 \
    "$output")

  if [[ -z "$part_duration" ]]; then
    echo "Fehler: Dauer von Teil $part konnte nicht ermittelt werden."
    exit 1
  fi

  total_part_duration=$(awk \
    -v total="$total_part_duration" \
    -v d="$part_duration" \
    'BEGIN { printf "%.6f", total + d }')

  echo "  Fertig: $((actual_size / 1000000)) MB, ${part_duration}s"

  # Nächster Start basiert auf der tatsächlichen Dauer des Teils
  start=$(awk \
    -v s="$start" \
    -v d="$part_duration" \
    'BEGIN { printf "%.6f", s + d }')

  # Neue Schätzung für den nächsten Teil
  chunk_duration=$(awk \
    -v d="$part_duration" \
    -v s="$actual_size" \
    -v t="$target_bytes" \
    'BEGIN { printf "%.6f", d * t / s }')

  ((part++))
done

echo
echo "Alle Teile wurden erstellt."
echo

# Endkontrolle: Gesamtdauer
difference=$(awk \
  -v total="$total_part_duration" \
  -v original="$duration" \
  'BEGIN { printf "%.6f", total - original }')

echo "Originaldauer:       ${duration}s"
echo "Summe der Teile:     ${total_part_duration}s"
echo "Differenz:           ${difference}s"

if awk -v d="$difference" \
  'BEGIN { exit !(d > 1 || d < -1) }'; then
  echo "WARNUNG: Die Gesamtdauer weicht um mehr als eine Sekunde ab."
else
  echo "Dauerprüfung:        OK"
fi

echo

# Ausgabedateien erst nach erfolgreicher Verarbeitung verschieben
for ((i=1; i<part; i++)); do
  destination="${input_dir}/${name}_Teil${i}.${extension}"
  if [[ -e "$destination" ]]; then
    echo "Fehler: Zieldatei existiert bereits: $destination"
    exit 1
  fi
done

for ((i=1; i<part; i++)); do
  src="${tmpdir}/Teil${i}.${extension}"
  destination="${input_dir}/${name}_Teil${i}.${extension}"

  mv -- "$src" "$destination" || exit 1
  echo "Erstellt: $destination"
done

echo
echo "Aufteilung abgeschlossen: $((part - 1)) Teile."
