#!/usr/bin/env sh
set -eu

# Public Wheelie installer template.
#
# The generated https://get.wheelie.dev script can bake in the current signed
# channel metadata and signing identity. This checked template keeps the public
# bootstrap behavior auditable: install only the global `wheelie` command from an
# immutable artifact, verify checksum/signature metadata, and do not install
# project-local overlays.

die() {
  printf '%s\n' "wheelie installer: $*" >&2
  exit 1
}

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

normalize_os() {
  os_name=$(uname -s | tr '[:upper:]' '[:lower:]')
  case "$os_name" in
    darwin) printf '%s' darwin ;;
    linux) printf '%s' linux ;;
    *) die "unsupported OS: $os_name" ;;
  esac
}

normalize_arch() {
  arch_name=$(uname -m)
  case "$arch_name" in
    arm64|aarch64) printf '%s' arm64 ;;
    x86_64|amd64) printf '%s' amd64 ;;
    *) die "unsupported architecture: $arch_name" ;;
  esac
}

sha256_file() {
  path=$1
  if command -v sha256sum >/dev/null 2>&1; then
    sha256sum "$path" | awk '{print $1}'
    return
  fi
  if command -v shasum >/dev/null 2>&1; then
    shasum -a 256 "$path" | awk '{print $1}'
    return
  fi
  die 'missing sha256sum or shasum for artifact verification'
}

normalize_sha256() {
  digest=$1
  case "$digest" in
    sha256:*) printf '%s' "${digest#sha256:}" ;;
    *) printf '%s' "$digest" ;;
  esac
}

verify_checksum() {
  artifact=$1
  checksum_file=$2
  expected=$(normalize_sha256 "$(awk '{print $1}' "$checksum_file")")
  actual=$(sha256_file "$artifact")
  if [ "$expected" != "$actual" ]; then
    die "checksum mismatch for $artifact"
  fi
}

verify_signature() {
  artifact=$1
  signature=$2
  if [ "${WHEELIE_ALLOW_UNSIGNED:-}" = "1" ]; then
    printf '%s\n' 'wheelie installer: WARNING signature verification bypassed by WHEELIE_ALLOW_UNSIGNED=1' >&2
    return
  fi
  need_command cosign
  cert_identity=${WHEELIE_COSIGN_CERT_IDENTITY:-}
  cert_identity_regexp=${WHEELIE_COSIGN_CERT_IDENTITY_REGEXP:-'https://github.com/wheelie-dev/wheelie/.github/workflows/wheelie-public-release.yml@refs/(heads/main|tags/v.*)'}
  oidc_issuer=${WHEELIE_COSIGN_CERT_OIDC_ISSUER:-https://token.actions.githubusercontent.com}
  if [ -n "$cert_identity" ]; then
    cosign verify-blob \
      --certificate-identity "$cert_identity" \
      --certificate-oidc-issuer "$oidc_issuer" \
      --signature "$signature" \
      "$artifact" >/dev/null
    return
  fi
  cosign verify-blob \
    --certificate-identity-regexp "$cert_identity_regexp" \
    --certificate-oidc-issuer "$oidc_issuer" \
    --signature "$signature" \
    "$artifact" >/dev/null
}

download() {
  url=$1
  destination=$2
  curl -fsSL -o "$destination" "$url"
}

metadata_value() {
  key=$1
  metadata_file=$2
  awk -F= -v wanted="$key" '$1 == wanted { sub(/^[^=]*=/, "", $0); print; exit }' "$metadata_file"
}

trim_trailing_slash() {
  value=$1
  while [ "${value%/}" != "$value" ]; do
    value=${value%/}
  done
  printf '%s' "$value"
}

write_install_receipt() {
  receipt_dir=$1
  receipt_path=$2
  mkdir -p "$receipt_dir"
  cat >"$receipt_path.tmp" <<EOF
{
  "schema_version": "wheelie_install_receipt/v1",
  "version": "$version",
  "channel": "$channel",
  "os": "$os",
  "arch": "$arch",
  "artifact_url": "$artifact_url",
  "artifact_digest": "sha256:$actual_sha256"
}
EOF
  mv "$receipt_path.tmp" "$receipt_path"
}

need_command curl
need_command tar
need_command awk

channel=${WHEELIE_CHANNEL:-stable}
version=${WHEELIE_VERSION:-latest}
os=$(normalize_os)
arch=$(normalize_arch)
install_dir=${WHEELIE_INSTALL_DIR:-"$HOME/.wheelie/bin"}
receipt_dir=${WHEELIE_RECEIPT_DIR:-"$HOME/.wheelie"}
release_base_url=$(trim_trailing_slash "${WHEELIE_RELEASE_BASE_URL:-https://get.wheelie.dev/releases}")
metadata_sha256=${WHEELIE_ARTIFACT_SHA256:-}
artifact_base_url=${WHEELIE_ARTIFACT_BASE_URL:-}
resolved_from_channel=0

case "$channel" in
  stable|canary) ;;
  *) die "unsupported channel: $channel" ;;
esac

case "$version" in
  ''|latest)
    channel_metadata_url="${release_base_url}/channels/${channel}.env"
    channel_metadata_path=$(mktemp "${TMPDIR:-/tmp}/wheelie-channel.XXXXXX")
    channel_metadata_sig_path="$channel_metadata_path.sig"
    trap 'rm -f "$channel_metadata_path" "$channel_metadata_sig_path"' EXIT HUP INT TERM
    download "$channel_metadata_url" "$channel_metadata_path"
    download "${channel_metadata_url}.sig" "$channel_metadata_sig_path"
    verify_signature "$channel_metadata_path" "$channel_metadata_sig_path"
    metadata_channel=$(metadata_value WHEELIE_CHANNEL "$channel_metadata_path")
    if [ "$metadata_channel" != "$channel" ]; then
      die "channel metadata mismatch: expected $channel got ${metadata_channel:-<empty>}"
    fi
    version=$(metadata_value WHEELIE_VERSION "$channel_metadata_path")
    metadata_sha256=$(metadata_value WHEELIE_ARTIFACT_SHA256 "$channel_metadata_path")
    artifact_base_url=$(metadata_value WHEELIE_ARTIFACT_BASE_URL "$channel_metadata_path")
    resolved_from_channel=1
    ;;
esac

[ -n "$version" ] || die 'release metadata did not provide WHEELIE_VERSION'
if [ "$resolved_from_channel" = "1" ] && [ -z "$metadata_sha256" ]; then
  die 'release metadata did not provide WHEELIE_ARTIFACT_SHA256'
fi
if [ -z "$artifact_base_url" ]; then
  artifact_base_url="${release_base_url}/artifacts/${version}"
fi
artifact_base_url=$(trim_trailing_slash "$artifact_base_url")

artifact_name="wheelie-${version}-${os}-${arch}.tar.gz"
artifact_url="${artifact_base_url}/${artifact_name}"
checksum_url="${artifact_url}.sha256"
signature_url="${artifact_url}.sig"

# Replace the channel-metadata cleanup trap with a full temp-dir cleanup once the
# artifact temp directory exists.
tmp_dir=$(mktemp -d "${TMPDIR:-/tmp}/wheelie-install.XXXXXX")
trap 'rm -rf "$tmp_dir"; rm -f "${channel_metadata_path:-}" "${channel_metadata_sig_path:-}"' EXIT HUP INT TERM

artifact_path="$tmp_dir/$artifact_name"
checksum_path="$artifact_path.sha256"
signature_path="$artifact_path.sig"
extract_dir="$tmp_dir/extract"

mkdir -p "$extract_dir" "$install_dir"

download "$artifact_url" "$artifact_path"
download "$checksum_url" "$checksum_path"
download "$signature_url" "$signature_path"

sidecar_sha256=$(normalize_sha256 "$(awk '{print $1}' "$checksum_path")")
if [ -n "$metadata_sha256" ]; then
  metadata_sha256=$(normalize_sha256 "$metadata_sha256")
  if [ "$metadata_sha256" != "$sidecar_sha256" ]; then
    die "channel metadata digest does not match checksum sidecar for $artifact_name"
  fi
fi

verify_checksum "$artifact_path" "$checksum_path"
verify_signature "$artifact_path" "$signature_path"
actual_sha256=$(sha256_file "$artifact_path")

tar -xzf "$artifact_path" -C "$extract_dir"
if [ ! -x "$extract_dir/wheelie" ]; then
  die 'release archive did not contain an executable wheelie file at archive root'
fi

install -m 0755 "$extract_dir/wheelie" "$install_dir/wheelie"
write_install_receipt "$receipt_dir" "$receipt_dir/install-receipt.json"
"$install_dir/wheelie" version >/dev/null

printf '%s\n' "wheelie installed to $install_dir/wheelie"
printf '%s\n' "artifact digest: sha256:$actual_sha256"
printf '%s\n' "Run 'wheelie doctor' to verify your environment."
