#!/bin/sh

set -eu

REPO="Jesssullivan/yt-text"
VERSION="latest"
PREFIX="${HOME}/.local"
BIN_DIR=""
SKIP_VERIFY=0
AUTH_TOKEN=""
BASE_URL=""
PUBLIC_DOWNLOAD_ROOT="https://transscendsurvival.org/yt-text/downloads"

usage() {
  cat <<'EOF'
Install yt-text from GitHub release artifacts.

Usage:
  install.sh [--version VERSION] [--prefix PREFIX] [--bin-dir DIR] [--repo OWNER/REPO] [--base-url URL] [--skip-verify]

Options:
  --version VERSION  Install a specific release tag or version number (default: latest)
  --prefix PREFIX    Install into PREFIX/bin when --bin-dir is not set (default: ~/.local)
  --bin-dir DIR      Install the yt-text binary into DIR directly
  --repo OWNER/REPO  Override the GitHub repository (default: Jesssullivan/yt-text)
  --base-url URL     Override the asset base URL directly
  --skip-verify      Skip SHA-256 verification against the published SHA256SUMS file
  -h, --help         Show this help text

Authentication:
  For private repositories, set GH_TOKEN or GITHUB_TOKEN before running the
  installer. If the GitHub CLI is already authenticated, install.sh also falls
  back to 'gh auth token'.
EOF
}

log() {
  printf '%s\n' "$*" >&2
}

fail() {
  log "error: $*"
  exit 1
}

need_cmd() {
  command -v "$1" >/dev/null 2>&1 || fail "missing required command: $1"
}

resolve_auth_token() {
  if [ -n "${GH_TOKEN:-}" ]; then
    printf '%s' "$GH_TOKEN"
    return 0
  fi

  if [ -n "${GITHUB_TOKEN:-}" ]; then
    printf '%s' "$GITHUB_TOKEN"
    return 0
  fi

  if command -v gh >/dev/null 2>&1; then
    gh auth token 2>/dev/null || true
    return 0
  fi

  return 0
}

normalize_version() {
  case "$1" in
    latest) printf '%s' "latest" ;;
    v*) printf '%s' "$1" ;;
    *) printf 'v%s' "$1" ;;
  esac
}

is_github_url() {
  case "$1" in
    https://github.com/*|https://api.github.com/*)
      return 0
      ;;
    *)
      return 1
      ;;
  esac
}

release_base_url() {
  tag="$1"

  if [ -n "$BASE_URL" ]; then
    printf '%s' "${BASE_URL%/}"
    return 0
  fi

  if [ "$REPO" = "Jesssullivan/yt-text" ]; then
    if [ "$tag" = "latest" ]; then
      printf '%s' "${PUBLIC_DOWNLOAD_ROOT%/}/latest"
    else
      printf '%s' "${PUBLIC_DOWNLOAD_ROOT%/}/${tag}"
    fi
    return 0
  fi

  if [ "$tag" = "latest" ]; then
    printf '%s' "https://github.com/${REPO}/releases/latest/download"
  else
    printf '%s' "https://github.com/${REPO}/releases/download/${tag}"
  fi
}

detect_asset() {
  os="$(uname -s)"
  arch="$(uname -m)"

  case "$os/$arch" in
    Darwin/arm64|Darwin/aarch64)
      printf '%s' "yt-text-aarch64-apple-darwin.tar.gz"
      ;;
    Darwin/x86_64)
      fail "Intel macOS is not published today. Use a source install or Nix instead."
      ;;
    Linux/x86_64|Linux/amd64)
      printf '%s' "yt-text-x86_64-unknown-linux-musl.tar.gz"
      ;;
    Linux/arm64|Linux/aarch64)
      printf '%s' "yt-text-aarch64-unknown-linux-musl.tar.gz"
      ;;
    *)
      fail "unsupported platform: $os/$arch"
      ;;
  esac
}

curl_download() {
  url="$1"
  destination="$2"

  if [ -n "$AUTH_TOKEN" ] && is_github_url "$url"; then
    if curl -fsSL \
      -H "Authorization: Bearer ${AUTH_TOKEN}" \
      -H "X-GitHub-Api-Version: 2022-11-28" \
      "$url" \
      -o "$destination"; then
      return 0
    fi

    fail "download failed for ${url} with GitHub authentication. Check the token and repo access."
  fi

  if curl -fsSL "$url" -o "$destination"; then
    return 0
  fi

  case "$url" in
    https://github.com/*|https://api.github.com/*)
      fail "download failed for ${url}. If the repo is private, export GH_TOKEN or GITHUB_TOKEN, or run 'gh auth login' first."
      ;;
    *)
      fail "download failed for ${url}"
      ;;
  esac
}

while [ $# -gt 0 ]; do
  case "$1" in
    --version)
      [ $# -ge 2 ] || fail "--version requires a value"
      VERSION="$2"
      shift 2
      ;;
    --prefix)
      [ $# -ge 2 ] || fail "--prefix requires a value"
      PREFIX="$2"
      shift 2
      ;;
    --bin-dir)
      [ $# -ge 2 ] || fail "--bin-dir requires a value"
      BIN_DIR="$2"
      shift 2
      ;;
    --repo)
      [ $# -ge 2 ] || fail "--repo requires a value"
      REPO="$2"
      shift 2
      ;;
    --base-url)
      [ $# -ge 2 ] || fail "--base-url requires a value"
      BASE_URL="$2"
      shift 2
      ;;
    --skip-verify)
      SKIP_VERIFY=1
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      fail "unknown argument: $1"
      ;;
  esac
done

if [ -z "$BIN_DIR" ]; then
  BIN_DIR="${PREFIX%/}/bin"
fi

need_cmd curl
need_cmd tar
need_cmd mktemp
need_cmd uname

AUTH_TOKEN="$(resolve_auth_token)"
ASSET_NAME="$(detect_asset)"
TAG="$(normalize_version "$VERSION")"
BASE_URL="$(release_base_url "$TAG")"
DISPLAY_VERSION="$TAG"

TMPDIR="$(mktemp -d)"
cleanup() {
  rm -rf "$TMPDIR"
}
trap cleanup EXIT HUP INT TERM

ASSET_PATH="${TMPDIR}/${ASSET_NAME}"
CHECKSUMS_PATH="${TMPDIR}/SHA256SUMS"

log "Downloading ${ASSET_NAME} from ${BASE_URL} (${DISPLAY_VERSION})..."
curl_download "${BASE_URL}/${ASSET_NAME}" "$ASSET_PATH"

if [ "$SKIP_VERIFY" -eq 0 ]; then
  log "Downloading SHA256SUMS..."
  curl_download "${BASE_URL}/SHA256SUMS" "$CHECKSUMS_PATH"

  EXPECTED_SUM="$(awk -v file="$ASSET_NAME" '$2 == file { print $1; exit }' "$CHECKSUMS_PATH")"
  [ -n "$EXPECTED_SUM" ] || fail "did not find a checksum for ${ASSET_NAME}"

  if command -v sha256sum >/dev/null 2>&1; then
    ACTUAL_SUM="$(sha256sum "$ASSET_PATH" | awk '{print $1}')"
  elif command -v shasum >/dev/null 2>&1; then
    ACTUAL_SUM="$(shasum -a 256 "$ASSET_PATH" | awk '{print $1}')"
  else
    fail "need sha256sum or shasum to verify downloads; rerun with --skip-verify to bypass"
  fi

  [ "$EXPECTED_SUM" = "$ACTUAL_SUM" ] || fail "checksum mismatch for ${ASSET_NAME}"
  log "Checksum verified."
fi

mkdir -p "$BIN_DIR"
tar -xzf "$ASSET_PATH" -C "$TMPDIR"
[ -f "${TMPDIR}/yt-text" ] || fail "archive did not contain a yt-text binary"

if command -v install >/dev/null 2>&1; then
  install -m 0755 "${TMPDIR}/yt-text" "${BIN_DIR}/yt-text"
else
  cp "${TMPDIR}/yt-text" "${BIN_DIR}/yt-text"
  chmod 0755 "${BIN_DIR}/yt-text"
fi

log "Installed yt-text to ${BIN_DIR}/yt-text"
log "Run '${BIN_DIR}/yt-text --version' to verify the install."
