#!/bin/sh
set -eu

rr_schema='radroots-install-script-v1'
rr_keys_url='https://radroots.dev/downloads/keys/KEYS'
rr_default_runtime='cli'
rr_runtime='cli'
rr_requested_version=''
rr_prefix=''
rr_bin_dir=''
rr_dry_run=0
rr_verify_only=0

rr_usage() {
  cat <<'RR_USAGE'
radroots install

usage
  curl --proto '=https' --tlsv1.2 -fsSL https://radroots.dev/install.sh | sh
  curl --proto '=https' --tlsv1.2 -fsSL https://radroots.dev/install.sh | sh -s -- --runtime cli
  curl --proto '=https' --tlsv1.2 -fsSL https://radroots.dev/install.sh | sh -s -- --runtime cli --version 0.1.0

options
  --runtime <key>     install cli or app
  --version <version> install a published version
  --prefix <path>     install under <path>/bin
  --bin-dir <path>    install directly into <path>
  --dry-run           verify and show the install target
  --verify-only       verify release files without installing
  -h, --help          show help

defaults
  runtime             cli
  prefix              $HOME/.radroots
RR_USAGE
}

rr_fail() {
  printf '\nerror: %s\n\n' "$1" >&2
  shift
  if [ "$#" -gt 0 ]; then
    printf '%s\n' "$@" >&2
    printf '\n' >&2
  fi
  exit 1
}

rr_step() {
  printf '✓ %s\n' "$1"
}

rr_need() {
  command -v "$1" >/dev/null 2>&1 || rr_fail "$1 is required" "next" "  install $1 and run this command again"
}

rr_fetch() {
  rr_fetch_url=$1
  rr_fetch_output=$2
  if command -v curl >/dev/null 2>&1; then
    curl --proto '=https' --tlsv1.2 -fsSL "$rr_fetch_url" -o "$rr_fetch_output" || rr_fail "download failed" "url" "  $rr_fetch_url"
    return 0
  fi
  if command -v wget >/dev/null 2>&1; then
    wget -q -O "$rr_fetch_output" "$rr_fetch_url" || rr_fail "download failed" "url" "  $rr_fetch_url"
    return 0
  fi
  rr_fail "curl or wget is required" "next" "  install curl or wget and run this command again"
}

rr_sha256_file() {
  if command -v sha256sum >/dev/null 2>&1; then
    rr_hash_output=$(sha256sum "$1")
    printf '%s\n' "${rr_hash_output%% *}"
    return 0
  fi
  if command -v shasum >/dev/null 2>&1; then
    rr_hash_output=$(shasum -a 256 "$1")
    printf '%s\n' "${rr_hash_output%% *}"
    return 0
  fi
  rr_fail "sha256sum or shasum is required" "next" "  install a SHA-256 checksum tool and run this command again"
}

rr_platform() {
  rr_os=$(uname -s 2>/dev/null || printf unknown)
  rr_arch=$(uname -m 2>/dev/null || printf unknown)
  case "$rr_os:$rr_arch" in
    Darwin:arm64|Darwin:aarch64) printf '%s\n' 'aarch64-apple-darwin' ;;
    *) rr_fail "platform is not published" "detected" "  os      $rr_os" "  arch    $rr_arch" "available" "  aarch64-apple-darwin" ;;
  esac
}

rr_parse_args() {
  while [ "$#" -gt 0 ]; do
    case "$1" in
      --runtime)
        [ "$#" -ge 2 ] || rr_fail "--runtime requires a value"
        rr_runtime=$2
        shift 2
        ;;
      --runtime=*)
        rr_runtime=${1#--runtime=}
        shift
        ;;
      --version)
        [ "$#" -ge 2 ] || rr_fail "--version requires a value"
        rr_requested_version=$2
        shift 2
        ;;
      --version=*)
        rr_requested_version=${1#--version=}
        shift
        ;;
      --prefix)
        [ "$#" -ge 2 ] || rr_fail "--prefix requires a path"
        rr_prefix=$2
        shift 2
        ;;
      --prefix=*)
        rr_prefix=${1#--prefix=}
        shift
        ;;
      --bin-dir)
        [ "$#" -ge 2 ] || rr_fail "--bin-dir requires a path"
        rr_bin_dir=$2
        shift 2
        ;;
      --bin-dir=*)
        rr_bin_dir=${1#--bin-dir=}
        shift
        ;;
      --dry-run)
        rr_dry_run=1
        shift
        ;;
      --verify-only)
        rr_verify_only=1
        shift
        ;;
      -h|--help)
        rr_usage
        exit 0
        ;;
      cli|app)
        rr_runtime=$1
        shift
        ;;
      *)
        rr_fail "unknown option: $1" "next" "  run with --help for supported options"
        ;;
    esac
  done
}

rr_select_release() {
  rr_known_runtime "$rr_runtime" || rr_fail "unknown runtime key" "requested" "  runtime  $rr_runtime" "available" "  cli" "  app"
  if [ -z "$rr_requested_version" ]; then
    rr_requested_version=$(rr_latest_version "$rr_runtime" 2>/dev/null || true)
    [ -n "$rr_requested_version" ] || rr_fail "runtime is not published yet" "requested" "  runtime  $rr_runtime" "available" "$(rr_available_summary)" "next" "  choose a published runtime key"
  fi
  rr_target=$(rr_platform)
  rr_release_fields "$rr_runtime" "$rr_requested_version" "$rr_target" || rr_fail "version is not published for this runtime and platform" "requested" "  runtime   $rr_runtime" "  version   $rr_requested_version" "  platform  $rr_target" "available versions" "$(rr_versions_for_runtime "$rr_runtime" 2>/dev/null || printf '  none\n')"
}

rr_prepare_paths() {
  if [ -z "$rr_prefix" ]; then
    if [ -n "${RADROOTS_INSTALL_ROOT:-}" ]; then
      rr_prefix=$RADROOTS_INSTALL_ROOT
    else
      [ -n "${HOME:-}" ] || rr_fail "HOME is required when --prefix or --bin-dir is not set"
      rr_prefix=$HOME/.radroots
    fi
  fi
  if [ -z "$rr_bin_dir" ]; then
    rr_bin_dir=$rr_prefix/bin
  fi
  rr_install_target=$rr_bin_dir/$rr_binary_name
}

rr_make_temp() {
  rr_tmp=$(mktemp -d "${TMPDIR:-/tmp}/radroots-install.XXXXXX") || rr_fail "could not create a temporary directory"
  trap 'rm -rf "$rr_tmp"' EXIT HUP INT TERM
}

rr_verify_release() {
  rr_need gpg
  rr_need tar
  rr_need grep
  rr_fetch "$rr_keys_url" "$rr_tmp/KEYS"
  rr_fetch "$rr_manifest_url" "$rr_tmp/release.json"
  rr_fetch "$rr_manifest_signature_url" "$rr_tmp/release.json.asc"
  rr_fetch "$rr_checksums_url" "$rr_tmp/SHA256SUMS"
  rr_fetch "$rr_checksums_signature_url" "$rr_tmp/SHA256SUMS.asc"
  rr_step "fetched release metadata"
  rr_gpg_home=$rr_tmp/gnupg
  mkdir -p "$rr_gpg_home"
  chmod 700 "$rr_gpg_home"
  gpg --batch --homedir "$rr_gpg_home" --import "$rr_tmp/KEYS" >/dev/null 2>&1 || rr_fail "could not import OpenPGP release keys"
  gpg --batch --homedir "$rr_gpg_home" --verify "$rr_tmp/release.json.asc" "$rr_tmp/release.json" >/dev/null 2>&1 || rr_fail "release metadata signature verification failed"
  gpg --batch --homedir "$rr_gpg_home" --verify "$rr_tmp/SHA256SUMS.asc" "$rr_tmp/SHA256SUMS" >/dev/null 2>&1 || rr_fail "SHA256SUMS signature verification failed"
  rr_step "verified OpenPGP signature"
  rr_archive_path=$rr_tmp/$rr_archive_name
  rr_fetch "$rr_archive_url" "$rr_archive_path"
  rr_actual_sha256=$(rr_sha256_file "$rr_archive_path")
  [ "$rr_actual_sha256" = "$rr_archive_sha256" ] || rr_fail "archive checksum mismatch" "expected" "  $rr_archive_sha256" "actual" "  $rr_actual_sha256"
  grep -F "$rr_archive_sha256  $rr_archive_name" "$rr_tmp/SHA256SUMS" >/dev/null 2>&1 || rr_fail "SHA256SUMS does not list the selected archive"
  rr_step "verified SHA256SUMS"
}

rr_extract_binary() {
  rr_unpack_dir=$rr_tmp/unpack
  mkdir -p "$rr_unpack_dir"
  tar -xzf "$rr_archive_path" -C "$rr_unpack_dir" || rr_fail "archive extraction failed"
  rr_extracted_binary=$rr_unpack_dir/$rr_archive_stem/bin/$rr_binary_name
  [ -f "$rr_extracted_binary" ] || rr_fail "archive did not contain the expected binary" "expected" "  $rr_archive_stem/bin/$rr_binary_name"
}

rr_install_binary() {
  if [ "$rr_verify_only" = 1 ]; then
    rr_step "verified install plan"
    printf '\nverified\n  runtime  %s\n  version  %s\n  target   %s\n\n' "$rr_runtime" "$rr_version" "$rr_target"
    exit 0
  fi
  if [ "$rr_dry_run" = 1 ]; then
    rr_step "verified install plan"
    printf '\nwould install\n  binary  %s\n  target  %s\n\n' "$rr_binary_name" "$rr_install_target"
    exit 0
  fi
  mkdir -p "$rr_bin_dir"
  if command -v install >/dev/null 2>&1; then
    install -m 0755 "$rr_extracted_binary" "$rr_install_target"
  else
    cp "$rr_extracted_binary" "$rr_install_target"
    chmod 755 "$rr_install_target"
  fi
  rr_step "installed radroots"
  printf '\ninstalled\n  binary  %s\n\n' "$rr_install_target"
  case ":$PATH:" in
    *":$rr_bin_dir:"*) ;;
    *) printf 'path\n  export PATH="%s:$PATH"\n\n' "$rr_bin_dir" ;;
  esac
}

rr_known_runtime() {
  case "$1" in
    'app') return 0 ;;
    'cli') return 0 ;;
    *) return 1 ;;
  esac
}

rr_latest_version() {
  case "$1" in
    'cli') printf '%s\n' '0.1.0' ;;
    *) return 1 ;;
  esac
}

rr_versions_for_runtime() {
  case "$1" in
    'cli')
      printf '  %s\n' '0.1.0'
      ;;
    *) return 1 ;;
  esac
}

rr_available_summary() {
  cat <<'RR_AVAILABLE'
  app      not published
  cli      0.1.0
RR_AVAILABLE
}

rr_release_fields() {
  case "$1:$2:$3" in
    'cli:0.1.0:aarch64-apple-darwin')
      rr_service='radroots_cli'
      rr_version='0.1.0'
      rr_release_channel='stable'
      rr_binary_name='radroots'
      rr_release_url='https://radroots.dev/downloads/releases/radroots_cli/0.1.0'
      rr_manifest_url='https://radroots.dev/downloads/releases/radroots_cli/0.1.0/release.json'
      rr_manifest_signature_url='https://radroots.dev/downloads/releases/radroots_cli/0.1.0/release.json.asc'
      rr_checksums_url='https://radroots.dev/downloads/releases/radroots_cli/0.1.0/SHA256SUMS'
      rr_checksums_signature_url='https://radroots.dev/downloads/releases/radroots_cli/0.1.0/SHA256SUMS.asc'
      rr_archive_url='https://radroots.dev/downloads/releases/radroots_cli/0.1.0/radroots_cli-0.1.0-aarch64-apple-darwin.tar.gz'
      rr_archive_name='radroots_cli-0.1.0-aarch64-apple-darwin.tar.gz'
      rr_archive_stem='radroots_cli-0.1.0-aarch64-apple-darwin'
      rr_archive_sha256='087151751d2f189feee2e98c1a180400ef35a74552c8a2911391ed4038f29090'
      rr_archive_byte_count='8429287'
      return 0
      ;;
    *) return 1 ;;
  esac
}

rr_parse_args "$@"
rr_select_release
rr_prepare_paths
printf 'radroots install\n\n'
printf 'runtime       %s\n' "$rr_runtime"
printf 'version       %s\n' "$rr_version"
printf 'platform      %s\n' "$rr_target"
printf 'install dir   %s\n\n' "$rr_bin_dir"
rr_make_temp
rr_verify_release
rr_extract_binary
rr_install_binary
