#!/usr/bin/env bash
# HP Envy menu helper: copy media into a Jellyfin NAS library.
# Existing video files:
#   /mnt/main-nas/movies/<Folder>/<video>
# Current mounted DVD folder, unchanged/no decryption:
#   /mnt/main-nas/movies/<Folder>/VIDEO_TS-or-disc-files

set -Eeuo pipefail

NAS_MOVIES_DIR="/mnt/main-nas/movies"
NAS_PORN_DIR="/mnt/main-nas/porn"
NAS_TV_DIR="/mnt/main-nas/tv-shows"

VIDEO_EXT_RE='\.(mp4|mkv|m4v|avi|mov|wmv|webm|ts|m2ts|mpg|mpeg|vob)$'
SIDECAR_EXT_RE='\.(srt|ass|ssa|sub|idx|nfo|jpg|jpeg|png|webp)$'

pause() {
  printf '\nPress Enter to return to the menu...'
  read -r _ || true
}

safe_folder_name() {
  local raw="$1"
  printf '%s' "$raw" \
    | tr '/:' '--' \
    | tr -cd '[:alnum:]. _()-' \
    | sed -E 's/[[:space:]]+/_/g; s/^_+|_+$//g; s/_+/_/g'
}

prompt_default() {
  local prompt="$1" default="$2" value
  printf '%s [%s]: ' "$prompt" "$default" >&2
  read -r value || value=""
  printf '%s' "${value:-$default}"
}

expand_path() {
  local p="$1"
  p="${p/#\~/$HOME}"
  printf '%s' "$p"
}

choose_library() {
  local choice
  while true; do
    cat >&2 <<MENU

Copy to which NAS Jellyfin library?
1. Movies    ($NAS_MOVIES_DIR)
2. Porn      ($NAS_PORN_DIR)
3. TV Shows  ($NAS_TV_DIR)
MENU
    printf 'Choose 1/2/3 [1]: ' >&2
    read -r choice || choice=""
    case "${choice:-1}" in
      1|movies|Movies|movie|Movie) printf '%s' "$NAS_MOVIES_DIR"; return 0 ;;
      2|porn|Porn) printf '%s' "$NAS_PORN_DIR"; return 0 ;;
      3|tv|TV|tvshows|TVShows|tv-shows|"tv shows"|"TV Shows"|tvshoes|TVShoes) printf '%s' "$NAS_TV_DIR"; return 0 ;;
      *) printf 'Invalid choice. Pick 1, 2, or 3.\n' >&2 ;;
    esac
  done
}

detect_dvd_source() {
  local candidate
  # Prefer real optical block devices over symlinks like /dev/cdrom.
  for candidate in /dev/sr0 /dev/sr1 /dev/sr2 /dev/dvd /dev/cdrom; do
    [[ -e "$candidate" ]] && { printf '%s' "$candidate"; return 0; }
  done
  printf '/dev/sr0'
}

dvd_mount_for_source() {
  local source="$1" resolved="" mount=""
  resolved="$(readlink -f "$source" 2>/dev/null || printf '%s' "$source")"
  # Match both the user-facing path (/dev/cdrom) and the real block device (/dev/sr0).
  mount="$(findmnt -rno SOURCE,TARGET,FSTYPE | awk -v src="$source" -v real="$resolved" '
    ($3=="udf" || $3=="iso9660") && ($1==src || $1==real) {print $2; exit}
  ')"
  if [[ -n "${mount// }" ]]; then
    printf '%s' "$mount"
    return 0
  fi
  # Fallback: if there is any mounted optical filesystem, use it.
  mount="$(findmnt -rno SOURCE,TARGET,FSTYPE | awk '
    ($3=="udf" || $3=="iso9660") && $1 ~ /^\/dev\/sr[0-9]+$/ {print $2; exit}
  ')"
  if [[ -n "${mount// }" ]]; then
    printf '%s' "$mount"
    return 0
  fi
  # Last fallback for desktop auto-mounts that appear under /media/$USER.
  for mount in /media/"$USER"/*; do
    [[ -d "$mount" ]] && { printf '%s' "$mount"; return 0; }
  done
  return 1
}

dvd_label_for_source() {
  local source="$1" label=""
  if [[ -b "$source" ]]; then
    label="$(lsblk -no LABEL "$source" 2>/dev/null | sed -n '1p' || true)"
  fi
  [[ -n "${label// }" ]] || label="DVD_Folder_$(date '+%Y%m%d')"
  printf '%s' "$label"
}

copy_video() {
  local src src_dir src_base src_stem default_folder folder library dest_dir dest_file copy_sidecars sidecar_count yn

  printf 'Existing video file path: '
  read -r src
  src="$(expand_path "$src")"

  if [[ ! -f "$src" ]]; then
    printf 'File not found: %s\n' "$src" >&2
    pause
    return 1
  fi

  if [[ ! "$src" =~ $VIDEO_EXT_RE ]]; then
    printf 'Warning: this does not look like a normal video file extension.\n' >&2
    printf 'Continue anyway? [y/N]: ' >&2
    read -r yn || yn=""
    [[ "$yn" =~ ^[Yy]$ ]] || { printf 'Cancelled.\n' >&2; pause; return 1; }
  fi

  src_dir="$(dirname "$src")"
  src_base="$(basename "$src")"
  src_stem="${src_base%.*}"
  default_folder="$(safe_folder_name "$src_stem")"
  [[ -n "${default_folder// }" ]] || default_folder="Video"

  library="$(choose_library)"
  if [[ ! -d "$library" ]]; then
    printf 'NAS library folder is not mounted/available: %s\n' "$library" >&2
    pause
    return 1
  fi

  folder="$(prompt_default 'Encapsulating folder name under that NAS library' "$default_folder")"
  folder="$(safe_folder_name "$folder")"
  [[ -n "${folder// }" ]] || folder="$default_folder"

  dest_dir="$library/$folder"
  dest_file="$dest_dir/$src_base"

  printf '\nSource video:\n  %s\n' "$src"
  printf 'Destination folder:\n  %s\n' "$dest_dir"
  printf 'Destination file:\n  %s\n' "$dest_file"

  if [[ -e "$dest_file" ]]; then
    printf '\nDestination file already exists. Refusing to overwrite:\n  %s\n' "$dest_file" >&2
    pause
    return 1
  fi

  printf '\nCopy matching sidecar files from the same folder? (.srt/.nfo/poster images) [Y/n]: ' >&2
  read -r copy_sidecars || copy_sidecars=""

  printf 'Proceed with copy? [Y/n]: ' >&2
  read -r yn || yn=""
  if [[ "$yn" =~ ^[Nn]$ ]]; then
    printf 'Cancelled before copying.\n' >&2
    pause
    return 1
  fi

  mkdir -p "$dest_dir"
  rsync -ah --info=progress2 "$src" "$dest_dir/"

  sidecar_count=0
  if [[ ! "$copy_sidecars" =~ ^[Nn]$ ]]; then
    shopt -s nullglob nocaseglob
    for f in "$src_dir/$src_stem".*; do
      [[ "$f" == "$src" ]] && continue
      [[ -f "$f" ]] || continue
      if [[ "$f" =~ $SIDECAR_EXT_RE ]]; then
        if [[ -e "$dest_dir/$(basename "$f")" ]]; then
          printf 'Skipping existing sidecar: %s\n' "$dest_dir/$(basename "$f")" >&2
        else
          rsync -ah "$f" "$dest_dir/"
          sidecar_count=$((sidecar_count + 1))
        fi
      fi
    done
    shopt -u nullglob nocaseglob
  fi

  if [[ ! -s "$dest_file" ]]; then
    printf 'Copy verification failed: destination file missing or empty: %s\n' "$dest_file" >&2
    pause
    return 1
  fi

  local src_size dest_size
  src_size="$(stat -c '%s' "$src")"
  dest_size="$(stat -c '%s' "$dest_file")"
  if [[ "$src_size" != "$dest_size" ]]; then
    printf 'Copy verification failed: source/destination sizes differ.\n' >&2
    printf 'Source bytes: %s\nDestination bytes: %s\n' "$src_size" "$dest_size" >&2
    pause
    return 1
  fi

  printf '\nCopy complete and verified.\n'
  printf 'Video: %s\n' "$dest_file"
  printf 'Sidecars copied: %s\n' "$sidecar_count"
  printf '\nNext: open Jellyfin and scan/refresh the matching library if it does not appear automatically:\n'
  printf '  http://main-nas.tail019015.ts.net:8096/web/\n'
  pause
}

copy_current_dvd_folder() {
  local source mount label default_folder folder library dest_dir yn src_bytes dest_bytes src_files dest_files
  source="$(detect_dvd_source)"
  mount="$(dvd_mount_for_source "$source" || true)"
  label="$(dvd_label_for_source "$source")"

  if [[ -z "${mount// }" || ! -d "$mount" ]]; then
    printf 'No mounted DVD folder found for %s. Insert/mount a disc first.\n' "$source" >&2
    pause
    return 1
  fi

  default_folder="$(safe_folder_name "$label")"
  [[ -n "${default_folder// }" ]] || default_folder="DVD_Folder"

  library="$(choose_library)"
  if [[ ! -d "$library" ]]; then
    printf 'NAS library folder is not mounted/available: %s\n' "$library" >&2
    pause
    return 1
  fi

  folder="$(prompt_default 'Encapsulating folder name under that NAS library' "$default_folder")"
  folder="$(safe_folder_name "$folder")"
  [[ -n "${folder// }" ]] || folder="$default_folder"
  dest_dir="$library/$folder"

  if [[ -e "$dest_dir" ]]; then
    printf '\nDestination folder already exists. Refusing to merge/overwrite:\n  %s\n' "$dest_dir" >&2
    pause
    return 1
  fi

  printf '\nCurrent DVD source: %s\n' "$source"
  printf 'Mounted DVD folder: %s\n' "$mount"
  printf 'DVD label: %s\n' "$label"
  printf 'Destination folder: %s\n' "$dest_dir"
  printf '\nImportant: this copies the DVD folder as-is. It does not decrypt, rip, or remove DRM.\n'
  printf 'If the disc is DRM-protected, Jellyfin may not be able to play the copied files.\n'
  printf '\nProceed with raw DVD folder copy? [Y/n]: ' >&2
  read -r yn || yn=""
  if [[ "$yn" =~ ^[Nn]$ ]]; then
    printf 'Cancelled before copying.\n' >&2
    pause
    return 1
  fi

  mkdir -p "$dest_dir"
  chmod u+rwx "$dest_dir" 2>/dev/null || true
  # Do not preserve read-only DVD directory permissions onto the NAS folder.
  # A mounted DVD is normally read-only; preserving that mode can make the
  # destination unwritable before VIDEO_TS/AUDIO_TS are created.
  rsync -rt --no-perms --no-owner --no-group --chmod=Du=rwx,Dgo=rx,Fu=rw,Fgo=r --info=progress2 "$mount"/ "$dest_dir"/

  src_files="$(find "$mount" -type f | wc -l)"
  dest_files="$(find "$dest_dir" -type f | wc -l)"
  src_bytes="$(du -sb "$mount" | awk '{print $1}')"
  dest_bytes="$(du -sb "$dest_dir" | awk '{print $1}')"

  if [[ "$src_files" != "$dest_files" ]]; then
    printf 'Copy verification warning: file counts differ. Source=%s Destination=%s\n' "$src_files" "$dest_files" >&2
    pause
    return 1
  fi

  printf '\nRaw DVD folder copy complete.\n'
  printf 'Destination: %s\n' "$dest_dir"
  printf 'Files copied: %s\n' "$dest_files"
  printf 'Approx source bytes: %s\nApprox destination bytes: %s\n' "$src_bytes" "$dest_bytes"
  printf '\nNext: open Jellyfin and scan/refresh the matching library:\n'
  printf '  http://main-nas.tail019015.ts.net:8096/web/\n'
  printf '\nReminder: this is not a decrypted MP4/MKV. Playback depends on Jellyfin/player support and the disc contents.\n'
  pause
}

status() {
  printf '\nNAS Jellyfin library folders\n'
  printf '===========================\n\n'
  for d in "$NAS_MOVIES_DIR" "$NAS_PORN_DIR" "$NAS_TV_DIR"; do
    if [[ -d "$d" ]]; then
      stat -c '%A %U:%G %n' "$d"
    else
      printf 'Missing/not mounted: %s\n' "$d"
    fi
  done
  printf '\nCurrent DVD mount, if any:\n'
  findmnt -rno SOURCE,TARGET,FSTYPE,OPTIONS | grep -Ei 'sr[0-9]|cdrom|dvd|udf|iso9660' || printf 'No mounted DVD found.\n'
  pause
}

case "${1:-copy}" in
  copy) copy_video ;;
  dvd-folder) copy_current_dvd_folder ;;
  status) status ;;
  *)
    printf 'Usage: %s [copy|dvd-folder|status]\n' "$(basename "$0")" >&2
    exit 2
    ;;
esac
