#!/usr/bin/bash
#
# beetbrainz-replay
#
# Manually replay spooled ListenBrainz scrobbles.
# Assumes a single-user beetbrainz --user service.

set -euo pipefail

SERVICE="beetbrainz.service"
LB_ENDPOINT="https://api.listenbrainz.org/1/submit-listens"
SLEEP_BETWEEN=2

# --------------------------------------------------------------------
# Help / usage
# --------------------------------------------------------------------
usage() {
  printf '%s\n' "Usage: beetbrainz-replay"
  printf '%s\n' ""
  printf '%s\n' "Manually replays spooled ListenBrainz scrobbles written by beetbrainz."
  printf '%s\n' ""
  printf '%s\n' "Options:"
  printf '%s\n' "  -h, --help    Show this help and exit"
}

if [ "${1:-}" ]; then
  case "$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" in
    -h|--help)
      usage
      exit 0
      ;;
    *)
      printf '%s\n' "Unknown option: $1" >&2
      usage >&2
      exit 1
      ;;
  esac
fi

# --------------------------------------------------------------------
# Load environment exported by the systemd --user service
# --------------------------------------------------------------------
while IFS= read -r env; do
  [ -n "$env" ] && export "$env"
done < <(
  systemctl --user show "$SERVICE" \
    --property=Environment --value \
    | tr ' ' '\n'
)

: "${BEETBRAINZ_SPOOL_DIR:?missing BEETBRAINZ_SPOOL_DIR}"
: "${USER_TOKENS:?missing USER_TOKENS}"

cd "$BEETBRAINZ_SPOOL_DIR"

# --------------------------------------------------------------------
# Resolve ListenBrainz token
# --------------------------------------------------------------------
LB_TOKEN="$(printf '%s\n' "$USER_TOKENS" | tr ' ' '\n' | awk -F: 'NR==1 {print $2}')"

if [ -z "$LB_TOKEN" ]; then
  printf '%s\n' "No ListenBrainz token available" >&2
  exit 1
fi

# --------------------------------------------------------------------
# Prevent concurrent replays
# --------------------------------------------------------------------
exec 9>"$BEETBRAINZ_SPOOL_DIR/.replay.lock"
if ! flock -n 9; then
  printf '%s\n' "Replay already running; exiting."
  exit 0
fi

# --------------------------------------------------------------------
# Detect replay files
# --------------------------------------------------------------------
shopt -s nullglob
files=(scrobbles-*.jsonl)
shopt -u nullglob

if [ "${#files[@]}" -eq 0 ]; then
  printf '%s\n' "No spooled scrobbles to replay."
  exit 0
fi

# --------------------------------------------------------------------
# Replay logic: ONE listen at a time
# --------------------------------------------------------------------
for file in "${files[@]}"; do
  printf 'Replaying %s\n' "$file"

  while [ -s "$file" ]; do
    line="$(head -n 1 "$file")"

    # Skip playing_now entries
    case "$line" in
      *'"listen_type":"playing_now"'*)
        tail -n +2 "$file" > "${file}.tmp"
        mv "${file}.tmp" "$file"
        continue
        ;;
    esac

    response="$(mktemp)"

    if ! status="$(
        curl --http1.1 -sS -o "$response" -w '%{http_code}' \
        -H "Authorization: Token $LB_TOKEN" \
        -H "Content-Type: application/json" \
        -H "Connection: close" \
        -X POST \
        -d "$line" \
        "$LB_ENDPOINT"
    )"; then
      printf '%s\n' "Transport failure during submission; aborting replay." >&2
      rm -f "$response"
      exit 1
    fi

    if [ "$status" -ne 200 ] && [ "$status" -ne 202 ]; then
      printf '%s\n' "Submission failed (HTTP $status); aborting replay." >&2
      printf '%s\n' "Response body:" >&2
      sed 's/^/  /' "$response" >&2
      rm -f "$response"
      exit 1
    fi

    rm -f "$response"

    # Remove successfully submitted line
    tail -n +2 "$file" > "${file}.tmp"
    mv "${file}.tmp" "$file"

    sleep "$SLEEP_BETWEEN"
  done

  rm -f "$file"
done

printf '%s\n' "Replay complete."
