#!/usr/bin/env bash
# Provision Transmission for Officer.
#
# Answers come from the environment; a human running this by hand is prompted for what is missing, but
# only when stdin is a TTY. See ../README.md for the contract every one of these obeys.
#
#   OFFICER_SERVICE_DIR   where to write. Everything this script creates is inside it.
#   OFFICER_UID/GID       who the container runs as
#   TRANSMISSION_PORT     RPC port on loopback              (default 9091)
#   TRANSMISSION_PEER_PORT  BitTorrent listen port          (default 51413)
#   TRANSMISSION_USER/PASS  optional RPC credentials        (default: none, loopback-only)
#
# Idempotent: safe to re-run, which is what makes a resumed install work rather than duplicate.

set -euo pipefail

SERVICE_DIR="${OFFICER_SERVICE_DIR:?OFFICER_SERVICE_DIR is required}"
TEMPLATE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

OFFICER_UID="${OFFICER_UID:-$(id -u)}"
OFFICER_GID="${OFFICER_GID:-$(id -g)}"
OFFICER_TZ="${OFFICER_TZ:-$(cat /etc/timezone 2>/dev/null || echo UTC)}"

# ── Asking ────────────────────────────────────────────────────────────────────────────────────────────
# A prompt behind a web form is a hang with no output. When the caller says it cannot answer, fail with
# the reason instead of blocking forever on a read nobody will ever satisfy.
ask() {
  local var="$1" prompt="$2" default="${3:-}"
  local current="${!var:-}"
  if [ -n "$current" ]; then return 0; fi
  if [ "${OFFICER_NONINTERACTIVE:-0}" = "1" ] || [ ! -t 0 ]; then
    if [ -n "$default" ]; then printf -v "$var" '%s' "$default"; return 0; fi
    echo "error: $var is required and this is a non-interactive run" >&2
    exit 2
  fi
  local answer
  read -r -p "$prompt${default:+ [$default]}: " answer
  printf -v "$var" '%s' "${answer:-$default}"
}

ask TRANSMISSION_PORT      'Transmission RPC port (loopback only)' '9091'
ask TRANSMISSION_PEER_PORT 'BitTorrent peer port'                  '51413'
TRANSMISSION_USER="${TRANSMISSION_USER:-}"
TRANSMISSION_PASS="${TRANSMISSION_PASS:-}"

# ── Render ────────────────────────────────────────────────────────────────────────────────────────────
echo "==> Preparing $SERVICE_DIR"
mkdir -p "$SERVICE_DIR/config" "$SERVICE_DIR/downloads" "$SERVICE_DIR/watch"

# envsubst with an explicit variable list, never the bare form: unrestricted envsubst would also expand
# anything in the template that merely looks like a variable, and a compose file is full of $ that
# belongs to other tools.
export OFFICER_UID OFFICER_GID OFFICER_TZ TRANSMISSION_PORT TRANSMISSION_PEER_PORT TRANSMISSION_USER TRANSMISSION_PASS
envsubst '${OFFICER_UID} ${OFFICER_GID} ${OFFICER_TZ} ${TRANSMISSION_PORT} ${TRANSMISSION_PEER_PORT} ${TRANSMISSION_USER} ${TRANSMISSION_PASS}' \
  < "$TEMPLATE_DIR/docker-compose.yaml" > "$SERVICE_DIR/docker-compose.yaml"

echo "==> Starting the container"
# `up -d` is already idempotent: an unchanged compose file against a running container is a no-op, and a
# changed one recreates. That is the whole reason a re-run is safe.
docker compose --project-directory "$SERVICE_DIR" up -d

# ── Wait ──────────────────────────────────────────────────────────────────────────────────────────────
# Reporting success the moment `up -d` returns would be a lie: the container exists, the RPC endpoint is
# not listening yet, and the platform's first call would fail against a service we just said was ready.
echo "==> Waiting for the RPC endpoint"
for i in $(seq 1 60); do
  # 409 is the correct healthy answer here — Transmission demands a session id and rejects the first
  # request by design. Treating only 200 as healthy would wait out the full timeout on a working daemon.
  code="$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${TRANSMISSION_PORT}/transmission/rpc" || true)"
  if [ "$code" = "409" ] || [ "$code" = "200" ] || [ "$code" = "401" ]; then
    echo "    up after ${i}s (HTTP $code)"
    break
  fi
  if [ "$i" = "60" ]; then
    echo "error: Transmission did not answer on 127.0.0.1:${TRANSMISSION_PORT} within 60s" >&2
    echo "       check: docker compose --project-directory '$SERVICE_DIR' logs" >&2
    exit 1
  fi
  sleep 1
done

# ── Hand the connection back ──────────────────────────────────────────────────────────────────────────
# Shape 1 from the README: we set the credentials, so nothing has to be asked for after the fact. These
# lines are the installer's only interface to this script's results — parsed by prefix, never by
# scraping the log above.
echo "OFFICER_RESULT_URL=http://127.0.0.1:${TRANSMISSION_PORT}"
echo "OFFICER_RESULT_PATH=/transmission/rpc"
echo "OFFICER_RESULT_USERNAME=${TRANSMISSION_USER}"
echo "OFFICER_RESULT_SECRET=${TRANSMISSION_PASS}"
echo "==> Done"
