#!/usr/bin/env bash
# avi2appletv_batch.sh
#
# Recursive batch convert *.avi -> Apple TV compatible MP4 on Raspberry Pi 4 (aarch64, 2GB).
# Safe for SSH disconnects: run with --start (systemd-run preferred, nohup fallback)
# Extensive logging + per-file logs + CSV and TXT reports (timings + frame counts best-effort).
#
# Usage:
#   chmod +x avi2appletv_batch.sh
#   ./avi2appletv_batch.sh --start "/path/to/folder"
#   ./avi2appletv_batch.sh --status
#   ./avi2appletv_batch.sh --tail "/path/to/folder"
#   ./avi2appletv_batch.sh --run  "/path/to/folder"   # foreground
#
# Env vars (optional):
#   OUT_DIR="AppleTV"            # if set: outputs go under OUT_DIR preserving input structure
#                               # if empty: output goes next to each .avi
#   OVERWRITE=0|1                # default 0
#   VERIFY_EXISTING=1            # default 1
#   RETRY_ON_FAIL=1              # default 1
#   SCALE_1080=1                 # default 1 (downscale >1080p to <=1080p)
#   CRF=23                       # default 23
#   PRESET="veryfast"            # default veryfast
#   AUDIO_BR="160k"              # default 160k
#   THREADS=3                    # default 3
#   NICE=10                      # default 10
#   IONICE_CLASS=2               # default 2
#   IONICE_LEVEL=7               # default 7
#   LOG_ROOT=""                  # default: <input_root>/.avi2appletv_logs

set -Eeuo pipefail

# -----------------------------
# Defaults
# -----------------------------
OUT_DIR="${OUT_DIR:-}"
OVERWRITE="${OVERWRITE:-0}"
VERIFY_EXISTING="${VERIFY_EXISTING:-1}"
RETRY_ON_FAIL="${RETRY_ON_FAIL:-1}"
SCALE_1080="${SCALE_1080:-1}"

CRF="${CRF:-23}"
PRESET="${PRESET:-veryfast}"
AUDIO_BR="${AUDIO_BR:-160k}"
THREADS="${THREADS:-3}"

NICE="${NICE:-10}"
IONICE_CLASS="${IONICE_CLASS:-2}"
IONICE_LEVEL="${IONICE_LEVEL:-7}"

LOG_ROOT="${LOG_ROOT:-}"

SERVICE_NAME="avi2appletv"

# -----------------------------
# Utilities
# -----------------------------
ts() { date "+%Y-%m-%d %H:%M:%S"; }
ns_now() { date +%s%N; }
ms_since() { local s="$1"; local e; e="$(ns_now)"; echo $(( (e - s)/1000000 )); }
human_ms() {
  local ms="$1"
  local s=$((ms/1000)); local rem_ms=$((ms%1000))
  local m=$((s/60)); local rem_s=$((s%60))
  local h=$((m/60)); local rem_m=$((m%60))
  if (( h>0 )); then printf "%dh %dm %ds.%03d" "$h" "$rem_m" "$rem_s" "$rem_ms"
  elif (( m>0 )); then printf "%dm %ds.%03d" "$m" "$rem_s" "$rem_ms"
  else printf "%ds.%03d" "$rem_s" "$rem_ms"; fi
}
require_bin() { command -v "$1" >/dev/null 2>&1 || { echo "ERROR: missing $1" >&2; exit 127; }; }
safe_mkdir() { mkdir -p "$1"; }

run_cmd() {
  if command -v ionice >/dev/null 2>&1; then
    nice -n "$NICE" ionice -c "$IONICE_CLASS" -n "$IONICE_LEVEL" "$@"
  else
    nice -n "$NICE" "$@"
  fi
}

# -----------------------------
# ffprobe helpers
# -----------------------------
probe_duration_s() { ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$1" 2>/dev/null || true; }
probe_codec() { ffprobe -v error -select_streams "$2" -show_entries stream=codec_name -of default=nw=1:nk=1 "$1" 2>/dev/null || true; }
probe_frames_best_effort() {
  ffprobe -v error -count_frames -select_streams v:0 \
    -show_entries stream=nb_read_frames -of default=nw=1:nk=1 "$1" 2>/dev/null | head -n 1 || true
}
probe_height() { ffprobe -v error -select_streams v:0 -show_entries stream=height -of default=nw=1:nk=1 "$1" 2>/dev/null || true; }

verify_output() {
  ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$1" >/dev/null 2>&1
}

build_vf() {
  local in_h="$1"
  [[ "$SCALE_1080" != "1" ]] && { echo ""; return; }
  if [[ -z "${in_h:-}" ]]; then
    echo "scale=w=1920:h=1080:force_original_aspect_ratio=decrease"
    return
  fi
  if [[ "$in_h" =~ ^[0-9]+$ ]] && (( in_h > 1080 )); then
    echo "scale=w=1920:h=1080:force_original_aspect_ratio=decrease"
  else
    echo ""
  fi
}

# -----------------------------
# Logging (set in run_batch)
# -----------------------------
RUN_ID=""
LOG_DIR=""
MAIN_LOG=""
CSV_REPORT=""
TXT_REPORT=""

log() { echo "[$(ts)] $*" | tee -a "$MAIN_LOG"; }
log_file() { local flog="$1"; shift; echo "[$(ts)] $*" | tee -a "$flog" >>"$MAIN_LOG"; }

# CSV escaping helper: wrap in quotes and escape quotes
csv_q() {
  local s="${1:-}"
  s="${s//\"/\"\"}"
  printf "\"%s\"" "$s"
}

# -----------------------------
# Output path mapping
# -----------------------------
map_output_path() {
  local in_file="$1"
  local in_root="$2"

  local rel="${in_file#"$in_root"/}"
  local rel_dir; rel_dir="$(dirname "$rel")"
  local base; base="$(basename "$in_file")"
  local name="${base%.*}"

  if [[ -z "$OUT_DIR" ]]; then
    echo "$(dirname "$in_file")/${name}.mp4"
  else
    echo "${OUT_DIR%/}/${rel_dir}/${name}.mp4"
  fi
}

# -----------------------------
# Encoding
# -----------------------------
encode_primary() {
  # $1=in $2=out_tmp $3=filelog $4=vf
  local in="$1" out_tmp="$2" flog="$3" vf="$4"
  local start_ns; start_ns="$(ns_now)"
  log_file "$flog" "FFmpeg(primary) start threads=$THREADS preset=$PRESET crf=$CRF vf=${vf:-<none>}"

  if [[ -n "$vf" ]]; then
    run_cmd ffmpeg -hide_banner -nostdin -y \
      -i "$in" \
      -map 0:v:0 -map 0:a:0? \
      -vf "$vf" \
      -c:v libx264 -threads "$THREADS" -preset "$PRESET" -crf "$CRF" \
      -profile:v high -level 4.1 -pix_fmt yuv420p \
      -c:a aac -b:a "$AUDIO_BR" \
      -movflags +faststart \
      "$out_tmp" >>"$flog" 2>&1
  else
    run_cmd ffmpeg -hide_banner -nostdin -y \
      -i "$in" \
      -map 0:v:0 -map 0:a:0? \
      -c:v libx264 -threads "$THREADS" -preset "$PRESET" -crf "$CRF" \
      -profile:v high -level 4.1 -pix_fmt yuv420p \
      -c:a aac -b:a "$AUDIO_BR" \
      -movflags +faststart \
      "$out_tmp" >>"$flog" 2>&1
  fi

  local rc=$?
  local ms; ms="$(ms_since "$start_ns")"
  log_file "$flog" "FFmpeg(primary) done rc=$rc time=$(human_ms "$ms")"
  echo "$rc,$ms"
}

encode_fallback() {
  # $1=in $2=out_tmp $3=filelog $4=vf
  local in="$1" out_tmp="$2" flog="$3" vf="$4"
  local start_ns; start_ns="$(ns_now)"
  log_file "$flog" "FFmpeg(fallback) start: fps=30 genpts level=4.0 preset=veryfast crf=24"

  local vf_full="fps=30"
  [[ -n "$vf" ]] && vf_full="fps=30,${vf}"

  run_cmd ffmpeg -hide_banner -nostdin -y \
    -fflags +genpts \
    -i "$in" \
    -map 0:v:0 -map 0:a:0? \
    -vf "$vf_full" \
    -c:v libx264 -threads "$THREADS" -preset veryfast -crf 24 \
    -profile:v high -level 4.0 -pix_fmt yuv420p \
    -c:a aac -b:a 160k -ar 48000 \
    -movflags +faststart \
    "$out_tmp" >>"$flog" 2>&1

  local rc=$?
  local ms; ms="$(ms_since "$start_ns")"
  log_file "$flog" "FFmpeg(fallback) done rc=$rc time=$(human_ms "$ms")"
  echo "$rc,$ms"
}

# -----------------------------
# Main runner
# -----------------------------
run_batch() {
  local input_root="$1"
  require_bin ffmpeg
  require_bin ffprobe

  if [[ ! -d "$input_root" ]]; then
    echo "ERROR: not a directory: $input_root" >&2
    exit 2
  fi
  input_root="$(cd "$input_root" && pwd -P)"

  # Make OUT_DIR absolute if set and relative
  if [[ -n "$OUT_DIR" && "$OUT_DIR" != /* ]]; then
    OUT_DIR="$input_root/$OUT_DIR"
  fi
  [[ -n "$OUT_DIR" ]] && safe_mkdir "$OUT_DIR"

  RUN_ID="$(date "+%Y%m%d_%H%M%S")"
  if [[ -z "$LOG_ROOT" ]]; then
    LOG_DIR="${input_root%/}/.avi2appletv_logs"
  else
    [[ "$LOG_ROOT" != /* ]] && LOG_ROOT="$input_root/$LOG_ROOT"
    LOG_DIR="$LOG_ROOT"
  fi
  safe_mkdir "$LOG_DIR"

  MAIN_LOG="$LOG_DIR/run_${RUN_ID}.log"
  CSV_REPORT="$LOG_DIR/report_${RUN_ID}.csv"
  TXT_REPORT="$LOG_DIR/report_${RUN_ID}.txt"

  # header
  echo "file,input_path,output_path,status,reason,input_frames,output_frames,input_duration_s,output_duration_s,probe_ms,convert_ms,verify_ms,total_ms,video_in,audio_in,video_out,audio_out,scaled_to_1080" >"$CSV_REPORT"

  log "Run ID        : $RUN_ID"
  log "Host          : $(hostname) | $(uname -a)"
  log "Input root    : $input_root"
  log "OUT_DIR       : ${OUT_DIR:-<same as input files>}"
  log "Options       : OVERWRITE=$OVERWRITE VERIFY_EXISTING=$VERIFY_EXISTING RETRY_ON_FAIL=$RETRY_ON_FAIL SCALE_1080=$SCALE_1080"
  log "Encode        : preset=$PRESET crf=$CRF audio=$AUDIO_BR threads=$THREADS"
  log "Priority      : nice=$NICE ionice=${IONICE_CLASS}:${IONICE_LEVEL}"
  log "Logs          : $MAIN_LOG"
  log "CSV report    : $CSV_REPORT"

  local run_start_ns; run_start_ns="$(ns_now)"
  local total_files=0 ok_files=0 skip_files=0 fail_files=0
  local total_probe_ms=0 total_convert_ms=0 total_verify_ms=0 total_total_ms=0

  # Recursive scan
  while IFS= read -r -d '' in_file; do
    ((total_files++)) || true

    local out_file; out_file="$(map_output_path "$in_file" "$input_root")"
    local out_dir; out_dir="$(dirname "$out_file")"
    safe_mkdir "$out_dir"

    local base; base="$(basename "$in_file")"
    local rel="${in_file#"$input_root"/}"
    local safe_rel="$rel"
    safe_rel="${safe_rel//\//_}"
    safe_rel="${safe_rel// /_}"
    local file_log="$LOG_DIR/${RUN_ID}_${safe_rel}.log"
    : >"$file_log"

    log "----------------------------------------"
    log "Processing: $in_file"
    log_file "$file_log" "Input : $in_file"
    log_file "$file_log" "Output: $out_file"

    local file_start_ns; file_start_ns="$(ns_now)"

    # Skip if output exists and verified
    if [[ -f "$out_file" && "$OVERWRITE" != "1" ]]; then
      if [[ "$VERIFY_EXISTING" == "1" ]]; then
        local vstart; vstart="$(ns_now)"
        if verify_output "$out_file"; then
          local vms; vms="$(ms_since "$vstart")"
          log_file "$file_log" "Output exists + verifies OK -> SKIP (verify_time=$(human_ms "$vms"))"
          ((skip_files++)) || true

          local pstart; pstart="$(ns_now)"
          local in_dur in_frames vin ain out_dur out_frames vout aout
          in_dur="$(probe_duration_s "$in_file")"
          in_frames="$(probe_frames_best_effort "$in_file")"
          vin="$(probe_codec "$in_file" "v:0")"
          ain="$(probe_codec "$in_file" "a:0")"
          out_dur="$(probe_duration_s "$out_file")"
          out_frames="$(probe_frames_best_effort "$out_file")"
          vout="$(probe_codec "$out_file" "v:0")"
          aout="$(probe_codec "$out_file" "a:0")"
          local pms; pms="$(ms_since "$pstart")"
          local ftotal_ms; ftotal_ms="$(ms_since "$file_start_ns")"

          echo "$(csv_q "$base"),$(csv_q "$in_file"),$(csv_q "$out_file"),SKIP,exists+verified,$(csv_q "$in_frames"),$(csv_q "$out_frames"),$(csv_q "$in_dur"),$(csv_q "$out_dur"),$pms,0,$vms,$ftotal_ms,$(csv_q "$vin"),$(csv_q "$ain"),$(csv_q "$vout"),$(csv_q "$aout")," >>"$CSV_REPORT"
          total_probe_ms=$((total_probe_ms+pms))
          total_verify_ms=$((total_verify_ms+vms))
          total_total_ms=$((total_total_ms+ftotal_ms))
          continue
        else
          local vms; vms="$(ms_since "$vstart")"
          log_file "$file_log" "Output exists but verify FAILED -> will re-encode (verify_time=$(human_ms "$vms"))"
          out_file="${out_file%.mp4}.reencoded_${RUN_ID}.mp4"
          out_dir="$(dirname "$out_file")"
          safe_mkdir "$out_dir"
          log_file "$file_log" "New output: $out_file"
        fi
      else
        log_file "$file_log" "Output exists and OVERWRITE=0 VERIFY_EXISTING=0 -> SKIP"
        ((skip_files++)) || true
        local pstart; pstart="$(ns_now)"
        local in_dur in_frames vin ain
        in_dur="$(probe_duration_s "$in_file")"
        in_frames="$(probe_frames_best_effort "$in_file")"
        vin="$(probe_codec "$in_file" "v:0")"
        ain="$(probe_codec "$in_file" "a:0")"
        local pms; pms="$(ms_since "$pstart")"
        local ftotal_ms; ftotal_ms="$(ms_since "$file_start_ns")"

        echo "$(csv_q "$base"),$(csv_q "$in_file"),$(csv_q "$out_file"),SKIP,exists,$(csv_q "$in_frames"),\"\",$(csv_q "$in_dur"),\"\",$pms,0,0,$ftotal_ms,$(csv_q "$vin"),$(csv_q "$ain"),\"\",\"\",\"\"" >>"$CSV_REPORT"
        total_probe_ms=$((total_probe_ms+pms))
        total_total_ms=$((total_total_ms+ftotal_ms))
        continue
      fi
    fi

    # Probe input
    local pstart; pstart="$(ns_now)"
    local in_dur in_frames in_h vin ain
    in_dur="$(probe_duration_s "$in_file")"
    in_frames="$(probe_frames_best_effort "$in_file")"
    in_h="$(probe_height "$in_file")"
    vin="$(probe_codec "$in_file" "v:0")"
    ain="$(probe_codec "$in_file" "a:0")"
    local vf; vf="$(build_vf "${in_h:-}")"
    local scaled_flag=""; [[ -n "$vf" ]] && scaled_flag="yes"
    local pms; pms="$(ms_since "$pstart")"
    total_probe_ms=$((total_probe_ms+pms))
    log_file "$file_log" "Probe: dur_s=${in_dur:-?} frames=${in_frames:-?} height=${in_h:-?} v=${vin:-?} a=${ain:-?} vf=${vf:-<none>} time=$(human_ms "$pms")"

    # Temp output then rename
    local name="${base%.*}"
    local out_tmp="$out_dir/.${name}.${RUN_ID}.tmp.mp4"
    rm -f "$out_tmp" 2>/dev/null || true
    [[ "$OVERWRITE" == "1" ]] && rm -f "$out_file" 2>/dev/null || true

    # Convert
    local c_rc=0 c_ms=0
    IFS=',' read -r c_rc c_ms < <(encode_primary "$in_file" "$out_tmp" "$file_log" "$vf") || true
    total_convert_ms=$((total_convert_ms+c_ms))

    if [[ "$c_rc" != "0" ]]; then
      log_file "$file_log" "Primary failed rc=$c_rc"
      if [[ "$RETRY_ON_FAIL" == "1" ]]; then
        rm -f "$out_tmp" 2>/dev/null || true
        local fb_rc=0 fb_ms=0
        IFS=',' read -r fb_rc fb_ms < <(encode_fallback "$in_file" "$out_tmp" "$file_log" "$vf") || true
        total_convert_ms=$((total_convert_ms+fb_ms))
        if [[ "$fb_rc" == "0" ]]; then
          c_rc=0
          c_ms=$((c_ms+fb_ms))
          log_file "$file_log" "Fallback succeeded"
        else
          log_file "$file_log" "Fallback failed rc=$fb_rc"
        fi
      fi
    fi

    # Move tmp to final
    if [[ "$c_rc" == "0" && -f "$out_tmp" ]]; then
      mv -f "$out_tmp" "$out_file" 2>>"$file_log" || c_rc=3
    else
      rm -f "$out_tmp" 2>/dev/null || true
    fi

    # Verify + probe output
    local vstart; vstart="$(ns_now)"
    local out_ok=0 out_dur out_frames vout aout
    out_dur=""; out_frames=""; vout=""; aout=""
    if [[ "$c_rc" == "0" && -f "$out_file" ]]; then
      verify_output "$out_file" && out_ok=1 || out_ok=0
      out_dur="$(probe_duration_s "$out_file")"
      out_frames="$(probe_frames_best_effort "$out_file")"
      vout="$(probe_codec "$out_file" "v:0")"
      aout="$(probe_codec "$out_file" "a:0")"
    fi
    local vms; vms="$(ms_since "$vstart")"
    total_verify_ms=$((total_verify_ms+vms))

    local ftotal_ms; ftotal_ms="$(ms_since "$file_start_ns")"
    total_total_ms=$((total_total_ms+ftotal_ms))

    local status reason
    if [[ "$c_rc" == "0" && "$out_ok" == "1" ]]; then
      status="OK"; reason=""
      ((ok_files++)) || true
      log_file "$file_log" "SUCCESS verify OK (verify=$(human_ms "$vms") total=$(human_ms "$ftotal_ms"))"
    else
      status="FAIL"
      reason=$([[ "$c_rc" != "0" ]] && echo "encode_failed_rc_$c_rc" || echo "verify_failed")
      ((fail_files++)) || true
      log_file "$file_log" "FAILED $reason (verify=$(human_ms "$vms") total=$(human_ms "$ftotal_ms"))"
    fi

    echo "$(csv_q "$base"),$(csv_q "$in_file"),$(csv_q "$out_file"),$status,$(csv_q "$reason"),$(csv_q "$in_frames"),$(csv_q "$out_frames"),$(csv_q "$in_dur"),$(csv_q "$out_dur"),$pms,$c_ms,$vms,$ftotal_ms,$(csv_q "$vin"),$(csv_q "$ain"),$(csv_q "$vout"),$(csv_q "$aout"),$(csv_q "$scaled_flag")" >>"$CSV_REPORT"

  done < <(find "$input_root" -type f -iname "*.avi" -print0)

  local run_total_ms; run_total_ms="$(ms_since "$run_start_ns")"

  {
    echo "AVI -> Apple TV MP4 Conversion Report (Pi4, recursive)"
    echo "Run ID        : $RUN_ID"
    echo "When          : $(ts)"
    echo "Host          : $(hostname)"
    echo "Kernel        : $(uname -r)"
    echo "Input root    : $input_root"
    echo "OUT_DIR       : ${OUT_DIR:-<same as input files>}"
    echo "Log dir       : $LOG_DIR"
    echo "Main log      : $MAIN_LOG"
    echo "CSV report    : $CSV_REPORT"
    echo ""
    echo "Summary"
    echo "  Total .avi found : $total_files"
    echo "  Converted OK     : $ok_files"
    echo "  Skipped          : $skip_files"
    echo "  Failed           : $fail_files"
    echo ""
    echo "Timing totals"
    echo "  Probe total   : $(human_ms "$total_probe_ms")"
    echo "  Convert total : $(human_ms "$total_convert_ms")"
    echo "  Verify total  : $(human_ms "$total_verify_ms")"
    echo "  Run total     : $(human_ms "$run_total_ms")"
    echo ""
    echo "Notes"
    echo "  - Existing outputs are verified and skipped when VERIFY_EXISTING=1."
    echo "  - Outputs are written to temp files then atomically renamed."
    echo "  - Frame counts are best-effort via ffprobe -count_frames (can be blank)."
  } | tee "$TXT_REPORT" | tee -a "$MAIN_LOG"

  log "Done."
  log "Report: $TXT_REPORT"
  log "CSV   : $CSV_REPORT"
}

# -----------------------------
# Background control
# -----------------------------
start_background() {
  local input_root="${1:-.}"
  input_root="$(cd "$input_root" && pwd -P)"

  # Ensure log dir exists so we can store last_unit
  local d="${LOG_ROOT:-$input_root/.avi2appletv_logs}"
  safe_mkdir "$d"

  local unit="${SERVICE_NAME}-$(date +%Y%m%d_%H%M%S)"

  if command -v systemd-run >/dev/null 2>&1; then
    echo "Starting background job via systemd-run (survives SSH disconnect)..."
    echo "$unit" > "$d/last_unit"

    # Run as a transient systemd service (system instance)
    systemd-run --unit="$unit" --property=Restart=no --collect \
      --property=WorkingDirectory="$input_root" \
      /usr/bin/env bash "$0" --run "$input_root"

    echo "Started unit: $unit"
    echo "Check status with: $0 --status \"$input_root\""
    echo "Tail logs with:    $0 --tail \"$input_root\""
  else
    echo "systemd-run not found; using nohup (survives SSH disconnect)..."
    echo "nohup" > "$d/last_unit"
    nohup /usr/bin/env bash "$0" --run "$input_root" >/dev/null 2>&1 &
    echo "Started with nohup. Logs under: $d"
  fi
}

status_background() {
  local root="${1:-.}"
  root="$(cd "$root" && pwd -P)"
  local d="${LOG_ROOT:-$root/.avi2appletv_logs}"

  if [[ ! -f "$d/last_unit" ]]; then
    echo "No last unit info found at: $d/last_unit"
    echo "Start a job with: $0 --start \"$root\""
    return 1
  fi

  local unit
  unit="$(cat "$d/last_unit")"

  if [[ "$unit" == "nohup" ]]; then
    echo "Last start used nohup. Checking logs/processes."
    status_fallback_from_logs "$root"
    return $?
  fi

  if ! command -v systemctl >/dev/null 2>&1; then
    echo "systemctl not available. Checking logs/processes."
    status_fallback_from_logs "$root"
    return $?
  fi

  # If unit still exists, show status. If not, fall back to logs.
  if systemctl list-units --all --type=service --no-legend | awk '{print $1}' | grep -qx "${unit}.service"; then
    systemctl status "${unit}.service" --no-pager || true
    # Also show last journal lines for convenience
    echo "---- last 40 journal lines for ${unit}.service ----"
    journalctl -u "${unit}.service" -n 40 --no-pager || true
  else
    echo "Unit ${unit}.service not found (finished/collected or failed early)."
    # If journald still has it, show it:
    if journalctl -u "${unit}.service" -n 5 --no-pager >/dev/null 2>&1; then
      echo "---- journal exists; last 40 lines ----"
      journalctl -u "${unit}.service" -n 40 --no-pager || true
      echo "--------------------------------------"
    fi
    status_fallback_from_logs "$root"
  fi
}

tail_background() {
  local root="${1:-.}"
  root="$(cd "$root" && pwd -P)"
  local d="${LOG_ROOT:-$root/.avi2appletv_logs}"
  if [[ ! -d "$d" ]]; then
    echo "No log dir found at: $d"
    exit 1
  fi
  local latest
  latest="$(ls -1t "$d"/run_*.log 2>/dev/null | head -n 1 || true)"
  if [[ -z "$latest" ]]; then
    echo "No run logs found in: $d"
    exit 1
  fi
  echo "Tailing: $latest"
  tail -n 200 -f "$latest"
}

usage() {
  cat <<EOF
Usage:
  $0 --start <folder>     Start conversion in background (systemd-run preferred)
  $0 --status             Show background service status (systemd)
  $0 --tail [folder]      Tail latest run log
  $0 --run <folder>       Run conversion in foreground

Examples:
  OUT_DIR="AppleTV" $0 --start /mnt/media
  $0 --status
  $0 --tail /mnt/media
EOF
}

status_fallback_from_logs() {
  local root="$1"
  local d="${LOG_ROOT:-$root/.avi2appletv_logs}"

  echo "Unit not present (may have finished/been collected)."
  echo "Log dir: $d"

  local latest_log
  latest_log="$(ls -1t "$d"/run_*.log 2>/dev/null | head -n 1 || true)"
  if [[ -z "$latest_log" ]]; then
    echo "No run logs found."
    return 1
  fi

  echo "Latest run log: $latest_log"
  echo "---- last 40 lines ----"
  tail -n 40 "$latest_log" || true
  echo "-----------------------"

  # Heuristic: if ffmpeg is currently running for this root, show it
  echo "Active ffmpeg processes (filtered):"
  pgrep -af "ffmpeg" | grep -F "$root" || echo "(none matching $root)"

  # Also show any running script instance
  echo "Active avi2appletv_batch.sh processes:"
  pgrep -af "avi2appletv_batch.sh" | grep -F "$root" || echo "(none matching $root)"

  return 0
}

# -----------------------------
# CLI
# -----------------------------
case "${1:-}" in
  --start)  start_background "${2:-.}" ;;
  --status) status_background "${2:-.}" ;;
  --tail)   tail_background "${2:-.}" ;;
  --run)    run_batch "${2:-.}" ;;
  -h|--help|"") usage ;;
  *) echo "ERROR: Unknown argument: $1" >&2; usage; exit 2 ;;
esac

