#!/usr/bin/env bash
# Terminal video player — mpv only (tct/kitty vo) with progress bar.

BRT_YTDLP_FORMAT="${BRT_YTDLP_FORMAT:-best[ext=mp4][vcodec^=avc1][height<=720]/best[ext=mp4][height<=720]/best[height<=720]/best[height<=480]}"

brt_video_tty() {
  if [[ -w /dev/tty ]]; then
    printf '/dev/tty'
  else
    printf '/dev/stdout'
  fi
}

brt_video_term_prepare() {
  local tty rows
  tty=$(brt_video_tty)
  rows=$(tput lines 2>/dev/null || echo 24)
  rows=$(( rows < 10 ? 24 : rows ))
  {
    # Alt-screen wheel → cursor keys, not scrollback (prevents tct corruption).
    printf '\033[?1007h'
    # Lock scroll region to the viewport so trailing newlines can't shift the canvas.
    printf '\033[1;%dr' "$rows"
  } >"$tty" 2>/dev/null || true
}

# Reinitialize the terminal after playback (mpv tct often skips cleanup on SIGINT).
brt_video_term_restore() {
  local tty vo="${BRT_VIDEO_VO:-}" rows cols
  [[ -w /dev/tty ]] || return 0
  tty=$(brt_video_tty)
  {
    [[ "$vo" == "kitty" ]] && printf '\033_Ga=d,a=A\033\\'
    printf '\033[?1007l\033[r\033[?1049l\033[?47l'
  } >"$tty" 2>/dev/null || true
  unset COLUMNS LINES
  if read -r rows cols _ < <(stty size 2>/dev/null <"$tty"); then
    stty rows "$rows" cols "$cols" <"$tty" 2>/dev/null || true
  fi
  reset >"$tty" 2>&1 <"$tty" || stty sane <"$tty" 2>/dev/null || true
  kill -WINCH $$ 2>/dev/null || true
}

brt_video_on_int() {
  brt_video_term_restore
}

brt_video_on_exit() {
  brt_video_term_restore
  unset BRT_VIDEO_VO
}

brt_video_input_conf() {
  local f
  f=$(mktemp "${TMPDIR:-/tmp}/brt-mpv-input.XXXXXX")
  cat > "$f" << 'EOF'
WHEEL_UP ignore
WHEEL_DOWN ignore
WHEEL_LEFT ignore
WHEEL_RIGHT ignore
EOF
  printf '%s' "$f"
}

brt_video_is_url() {
  [[ "${1:-}" =~ ^https?:// ]]
}

brt_video_resolve_local_path() {
  local p="$1" dir base
  case "$p" in
    ~/*) p="${HOME}/${p#~/}" ;;
    ~) p="$HOME" ;;
  esac
  if [[ ! -f "$p" ]]; then
    return 1
  fi
  if command -v realpath &>/dev/null; then
    realpath "$p"
    return 0
  fi
  dir=$(cd "$(dirname "$p")" 2>/dev/null && pwd) || return 1
  base=$(basename "$p")
  printf '%s/%s' "$dir" "$base"
}

brt_video_is_youtube() {
  [[ "${1:-}" =~ (youtube\.com|youtu\.be|youtube-nocookie\.com) ]]
}

brt_video_ytdlp() {
  if command -v yt-dlp &>/dev/null; then
    printf '%s' "yt-dlp"
    return 0
  fi
  if command -v youtube-dl &>/dev/null; then
    printf '%s' "youtube-dl"
    return 0
  fi
  return 1
}

brt_video_resolve_youtube() {
  local url="$1" ytdlp stream
  ytdlp=$(brt_video_ytdlp) || return 1
  stream=$("$ytdlp" --no-playlist -f "${BRT_YTDLP_FORMAT}" -g "$url" 2>/dev/null | head -1)
  if [[ -z "$stream" ]]; then
    stream=$("$ytdlp" --no-playlist -f best -g "$url" 2>/dev/null | head -1)
  fi
  [[ -n "$stream" ]] || return 1
  printf '%s' "$stream"
}

brt_video_vo_supported() {
  local vo="$1" help
  help=$(mpv --vo=help 2>/dev/null || true)
  [[ -n "$help" ]] && grep -qE "(^|[[:space:]])${vo}([[:space:]]|$)" <<< "$help"
}

brt_video_pick_vo() {
  local force="${BRT_VIDEO_VO_FORCE:-}" vo

  if [[ -n "$force" ]] && brt_video_vo_supported "$force"; then
    printf '%s' "$force"
    return 0
  fi

  if [[ "${TERM_PROGRAM:-}" == *[Gg]hostty* ]] && brt_video_vo_supported tct; then
    printf '%s' "tct"
    return 0
  fi

  for vo in tct kitty; do
    if brt_video_vo_supported "$vo"; then
      printf '%s' "$vo"
      return 0
    fi
  done
  return 1
}

brt_video_tct_algo() {
  local algo="${BRT_TCT_ALGO:-half-blocks}"
  case "$algo" in
    plain|half-blocks) printf '%s' "$algo" ;;
    *) printf '%s' "half-blocks" ;;
  esac
}

brt_video_size() {
  local cols rows
  cols=0
  rows=0

  if [[ -r /dev/tty ]]; then
    read -r rows cols _ < <(stty size 2>/dev/null </dev/tty) || true
  fi
  if ! [[ "$cols" =~ ^[0-9]+$ && "$rows" =~ ^[0-9]+$ && "$cols" -gt 0 && "$rows" -gt 0 ]]; then
    cols=$(tput cols 2>/dev/null || echo 80)
    rows=$(tput lines 2>/dev/null || echo 24)
  fi

  cols=$(( cols < 10 ? 80 : cols ))
  rows=$(( rows < 10 ? 24 : rows ))
  printf '%s %s\n' "$cols" "$rows"
}

brt_video_user_ok() {
  local rc="${1:-0}"
  (( rc == 0 || rc == 130 || rc == 143 ))
}

brt_video_play() {
  local source="$1"
  local audio="$2"
  local cols rows vo algo rc=0 log input_conf
  local -a mpv_args=()
  local -a network_args=()

  read -r cols rows < <(brt_video_size)
  vo=$(brt_video_pick_vo) || return 127
  export BRT_VIDEO_VO="$vo"
  algo=$(brt_video_tct_algo)
  log=$(mktemp "${TMPDIR:-/tmp}/brt-mpv.XXXXXX")
  input_conf=$(brt_video_input_conf)

  brt_video_term_prepare

  mpv_args=(
    --quiet
    --terminal=no
    --input-terminal=yes
    --input-conf="$input_conf"
    --msg-level=all=no
    --log-file="$log"
    --force-window=no
    --keep-open=no
    --term-osd=force
    --term-osd-bar=yes
    --term-status-msg='${time-pos}/${duration} (${percent-pos}%)'
    --vo="$vo"
    --keepaspect=no
    --panscan=1.0
    --video-unscaled=no
    --autosync=30
    --video-sync=display-resample
    --cache=yes
    --cache-pause=no
    --demuxer-readahead-secs=30
    --cache-secs=90
    --profile=sw-fast
  )

  case "$vo" in
    tct)
      mpv_args+=(
        --vo-tct-width="$cols"
        --vo-tct-height="$rows"
        --vo-tct-algo="$algo"
        --vo-tct-buffering=frame
        --monitorpixelaspect=0.5
      )
      ;;
    kitty)
      mpv_args+=(
        --vo-kitty-alt-screen=yes
        --vo-kitty-config-clear=yes
        --vo-kitty-cols="$cols"
        --vo-kitty-rows="$rows"
      )
      ;;
  esac

  if brt_video_is_youtube "$source"; then
    local stream
    if stream=$(brt_video_resolve_youtube "$source"); then
      source="$stream"
      network_args=(
        --network-timeout=120
        --stream-lavf-o=reconnect=1,reconnect_streamed=1,reconnect_delay_max=5,fflags=+discardcorrupt
      )
    else
      network_args=(--ytdl=yes --ytdl-format="${BRT_YTDLP_FORMAT}" --network-timeout=120)
    fi
  elif brt_video_is_url "$source"; then
    network_args=(
      --network-timeout=60
      --stream-lavf-o=reconnect=1,reconnect_streamed=1,reconnect_delay_max=5,fflags=+discardcorrupt
    )
  else
    local resolved
    if ! resolved=$(brt_video_resolve_local_path "$source"); then
      brt_error "Not found: ${source}"
      rm -f "$log" "$input_conf"
      return 1
    fi
    source="$resolved"
    network_args=(--no-ytdl)
  fi

  if ((${#network_args[@]} > 0)); then
    mpv_args+=("${network_args[@]}")
  fi
  (( audio )) || mpv_args+=(--no-audio)

  # Foreground mpv keeps keyboard input; restore runs on INT trap and again after exit.
  mpv "${mpv_args[@]}" "$source" 2>/dev/null
  rc=$?
  if ! brt_video_user_ok "$rc" && [[ -s "$log" ]]; then
    tail -5 "$log" >&2
  fi
  rm -f "$log" "$input_conf"
  brt_video_term_restore
  return "$rc"
}

brt_video() {
  local source="${1:-}"
  local audio=1 rc

  if [[ -z "$source" ]]; then
    brt_error "Usage: brt -video <file|url> [--no-audio]"
    brt_info "Terminal video via mpv — space pause, q quit, arrows seek"
    brt_info "Press q to quit — terminal restores automatically on exit"
    brt_info "Supports local files, HTTP URLs, and YouTube links"
    exit 1
  fi

  shift
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --no-audio) audio=0; shift ;;
      -x|-y|-w|--width|-fps)
        brt_warn "Deprecated option ignored: $1 (video fills the terminal)"
        shift 2
        ;;
      --tiny-font|--no-tiny-font)
        brt_warn "Deprecated option ignored: $1"
        shift
        ;;
      *)
        brt_error "Unknown option: $1"
        brt_info "Usage: brt -video <file|url> [--no-audio]"
        exit 1
        ;;
    esac
  done

  command -v mpv &>/dev/null || {
    brt_error "mpv is required for video playback"
    brt_info "Install: brew install mpv"
    exit 1
  }

  if brt_video_is_youtube "$source" && ! brt_video_ytdlp &>/dev/null; then
    brt_warn "Install yt-dlp for reliable YouTube: brew install yt-dlp"
  fi

  trap 'brt_video_on_int' INT
  trap 'brt_video_on_exit' EXIT

  set +e
  brt_video_play "$source" "$audio"
  rc=$?
  set -e

  if brt_video_user_ok "$rc"; then
    return 0
  fi
  brt_error "Playback failed (exit ${rc})"
  return "$rc"
}
