#!/usr/bin/env bash
#
# make_mix.sh turn a tracklist into a playable mix (with auto-dependency installer).

set -euo pipefail

# ---- defaults ---------------------------------------------------------------
name=""
parent="."
maxdur=900
play=1
playonly=0
input=""

die() { printf '%s\n' "$*" >&2; exit 1; }

# ---- auto-dependency installer ----------------------------------------------
install_dependencies() {
  local missing=()
  for tool in yt-dlp ffmpeg mpv; do
    if ! command -v "$tool" >/dev/null 2>&1; then
      missing+=("$tool")
    fi
  done

  if [ ${#missing[@]} -eq 0 ]; then
    return 0
  fi

  printf 'Missing dependencies found: %s\n' "${missing[*]}"
  printf 'Attempting to install them automatically...\n'

  # Detect OS / Package Manager
  if [[ "$OSTYPE" == "darwin"* ]]; then
    if ! command -v brew >/dev/null 2>&1; then
      die "Homebrew is required to install dependencies on macOS. Install it from https://brew.sh"
    fi
    brew install "${missing[@]}"
  elif [ -f /etc/debian_version ]; then
    printf 'Elevated privileges (sudo) may be required to run apt-get.\n'
    sudo apt-get update
    
    # Map yt-dlp for apt since older Debian/Ubuntu distros might not have it natively
    local apt_packages=()
    for tool in "${missing[@]}"; do
      if [ "$tool" = "yt-dlp" ]; then
        # Install python3-pip if yt-dlp isn't in standard apt
        sudo apt-get install -y python3-pip python3-venv || true
        pip3 install --break-system-packages yt-dlp || pip3 install yt-dlp || apt_packages+=("yt-dlp")
      else
        apt_packages+=("$tool")
      fi
     Dil   done
    if [ ${#apt_packages[@]} -gt 0 ]; then
      sudo apt-get install -y "${apt_packages[@]}"
    fi
  elif [ -f /etc/redhat-release ] || [ -f /etc/fedora-release ]; then
    printf 'Elevated privileges (sudo) may be required to run dnf.\n'
    sudo dnf install -y "${missing[@]}"
  elif [ -f /etc/arch-release ]; then
    printf 'Elevated privileges (sudo) may be required to run pacman.\n'
    sudo pacman -Syu --noconfirm "${missing[@]}"
  else
    die "Unsupported operating system. Please manually install: ${missing[*]}"
  fi

  # Final verification pass
  for tool in yt-dlp ffmpeg mpv; do
    command -v "$tool" >/dev/null 2>&1 || die "Installation failed for $tool. Please install it manually."
  done
  printf 'All dependencies successfully installed!\n\n'
}

# ---- options ----------------------------------------------------------------
while [ $# -gt 0 ]; do
  case "$1" in
    "-n") name="${2:-}"; shift 2 ;;
    "-d") parent="${2:-}"; shift 2 ;;
    "-m") maxdur="${2:-}"; shift 2 ;;
    --no-play)   play=0; shift ;;
    --play-only) playonly=1; shift ;;
    "-h"|--help)
      sed -n '2,/^set -euo/p' "$0" | sed 's/^# \{0,1\}//; s/^#//' | sed '$d'
      exit 0 ;;
    --) shift; break ;;
    -*) die "unknown option: $1" ;;
    *)  input="$1"; shift ;;
  esac
done
[ $# -gt 0 ] && [ -z "$input" ] && input="$1"

# ---- name / dirs ------------------------------------------------------------
if [ -z "$name" ]; then
  if [ -n "$input" ] && [ "$input" != "-" ]; then
    base="$(basename -- "$input")"
    name="${base%.*}"
  else
    name="new_mix20260728"
  fi
fi

dir="$parent/$name"
playlist="$dir/$name.m3u"

sanitize() { printf '%s' "$1" | tr '/' '-' | tr -d '\000'; }

# ---- check/install tools ----------------------------------------------------
install_dependencies

# ---- play-only shortcut -----------------------------------------------------
if [ "$playonly" -eq 1 ]; then
  files=()
  if [ -f "$playlist" ]; then
    while IFS= read -r f; do
      [ -n "$f" ] || continue
      case "$f" in \#*) continue ;; esac
      files+=("$dir/$f")
    done < "$playlist"
  else
    while IFS= read -r f; do files+=("$f"); done \
      < <(find "$dir" -maxdepth 1 -name '*.mp3' | sort)
  fi
  [ "${#files[@]}" -gt 0 ] || die "nothing to play in $dir"
  exec mpv --no-video "${files[@]}"
fi

# ---- input ------------------------------------------------------------------
if [ -z "$input" ]; then
  if [ ! -t 0 ]; then
    src=/dev/stdin
  else
    src="$(mktemp)"
    trap 'rm -f "$src"' EXIT
    cat << 'EMBEDDED_TRACKS' > "$src"
Graham Central Station - The Jam
MC5 - Ramblin' Rose
Pere Ubu - Street Waves
Link Wray - Rumble
Wipers - D-7
Echo & the Bunnymen - All That Jazz
Breaking Circus - Laid So Low
Jay Reatard - It's So Easy
Coachwhips - Yes I'm Down
Milemarker - New Lexicon
Sunny Day Real Estate - Circles
Russian Circles - Youngblood
The Notwist - Pilot
Turbonegro - Get It On
Alice Cooper - I'm Eighteen
The Cadillacs - Speedo
Del Shannon - Runaway
Kings of Nuthin' - Old Habits Die Hard
Human Sexual Response - What Does Sex Mean to Me?
Killing Joke - The Wait
Television - See No Evil
The Congos - Fisherman
The Gladiators - Roots Natty
Anthrax - Caught in a Mosh
Overkill - Hello from the Gutter
Exodus - The Toxic Waltz
Les Paul & Mary Ford - How High the Moon
Jackie Brenston - Rocket 88
The Monks - Complications
The Sonics - Strychnine
Chris Bell - I Am the Cosmos
Germs - Lexicon Devil
Rodriguez - Sugar Man
The Modern Lovers - Roadrunner
The Sound - Sense of Purpose
The Chameleons - Second Skin
Magazine - Shot by Both Sides
Rowland S. Howard - Shivers
Death Angel - Voracious Souls
Testament - Over the Wall
EMBEDDED_TRACKS
  fi
elif [ "$input" = "-" ]; then
  src=/dev/stdin
else
  [ -f "$input" ] || die "no such tracklist: $input"
  src="$input"
fi

mkdir -p "$dir"

# ---- fetch loop -------------------------------------------------------------
count=0
files=()
while IFS= read -r raw || [ -n "$raw" ]; do
  line="${raw%$'\r'}"
  line="$(printf '%s' "$line" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
  [ -n "$line" ] || continue
  case "$line" in \#*) continue ;; esac

  # drop a leading "1." / "1)" / "-" / "*" enumerator
  query="$(printf '%s' "$line" | sed -E 's/^([0-9]+[.)]|[-*])[[:space:]]+//')"
  [ -n "$query" ] || continue

  next="$(printf '%02d' "$((count + 1))")"
  label="$(sanitize "$query")"
  final="$dir/$next - $label.mp3"

  if [ -f "$final" ]; then
    printf '[%s] have  %s\n' "$next" "$query"
    count="$((count + 1))"
    files+=("$final")
    continue
  fi

  printf '[%s] fetch %s\n' "$next" "$query"
  if yt-dlp \
        "-x" --audio-format mp3 --audio-quality 0 \
        --embed-metadata \
        --match-filter "duration < $maxdur" \
        --no-playlist \
        "-o" "$dir/$next - $label.%(ext)s" \
        "ytsearch1:$query"
  then
    if [ "-f" "$final" ]; then
      count="$((count + 1))"
      files+=("$final")
    else
      printf '  !! no match under %ss: %s\n' "$maxdur" "$query" >&2
    fi
  else
    printf '  !! failed: %s\n' "$query" >&2
  fi
done < "$src"

[ "${#files[@]}" -gt 0 ] || die "nothing downloaded"

# ---- playlist ---------------------------------------------------------------
: > "$playlist"
for f in "${files[@]}"; do
  printf '%s\n' "$(basename -- "$f")" >> "$playlist"
done
printf '\n%d tracks -> %s\n' "${#files[@]}" "$dir"

# ---- play -------------------------------------------------------------------
if [ "$play" -eq 1 ]; then
  exec mpv --no-video "${files[@]}"
fi