#!/usr/bin/env bash
# Install the soldr binary used by build/lint/test to route Rust toolchain
# calls through `rustup which`. soldr is intentionally NOT a Python dep —
# it ships as a standalone binary published to GitHub Releases.
#
# Default: install into this repo's .venv ({Scripts,bin}/soldr[.exe]).
# With --global: install into ~/.cargo/bin (or ~/.local/bin if absent).

set -euo pipefail

# Keep in lockstep with pyproject.toml's `build-system.requires` and the
# `setup-soldr` versions under .github/ — a developer whose
# local soldr trails CI's cannot reproduce a CI failure. All three are one
# decision; `tests/test_packaging_metadata.py` asserts they agree. See DD-020.
VERSION="${SOLDR_VERSION:-0.8.44}"
GLOBAL=0

usage() {
    cat <<EOF
Usage: ./install [--global] [--version=VERSION]

Installs soldr (https://github.com/zackees/soldr) — a thin wrapper around
the rustup-managed cargo/rustc/rustfmt that this repo's build scripts
expect on PATH.

Options:
  --global              Install to ~/.cargo/bin (or ~/.local/bin) instead
                        of the local .venv. Useful if you work across
                        multiple Rust repos.
  --version=VERSION     Pin a specific soldr version (default: ${VERSION}).
  -h, --help            Show this message.

Environment:
  SOLDR_VERSION         Same as --version.
EOF
}

for arg in "$@"; do
    case "$arg" in
        --global) GLOBAL=1 ;;
        --version=*) VERSION="${arg#--version=}" ;;
        -h|--help) usage; exit 0 ;;
        *) echo "unknown arg: $arg" >&2; usage >&2; exit 2 ;;
    esac
done

uname_s=$(uname -s)
uname_m=$(uname -m)

case "$uname_m" in
    x86_64|amd64) arch=x86_64 ;;
    aarch64|arm64) arch=aarch64 ;;
    *) echo "unsupported architecture: $uname_m" >&2; exit 1 ;;
esac

case "$uname_s" in
    Linux*)   triple="${arch}-unknown-linux-gnu"; ext=tar.gz; binary="soldr" ;;
    Darwin*)  triple="${arch}-apple-darwin";      ext=tar.gz; binary="soldr" ;;
    MINGW*|MSYS*|CYGWIN*|Windows_NT)
              triple="${arch}-pc-windows-msvc";   ext=zip;    binary="soldr.exe" ;;
    *) echo "unsupported OS: $uname_s" >&2; exit 1 ;;
esac

# Use the release's wheel for current soldr versions.
#
# soldr 0.8.x stopped publishing `.tar.gz`/`.zip` and ships `.tar.zst` only,
# which needs a `zstd` binary this script cannot assume — git-bash on Windows
# has GNU tar but no zstd, so even `tar --zstd` fails with "Cannot exec". The
# wheel is a plain zip carrying the same binary under
# `soldr-<version>.data/scripts/`, and the extraction below already handles
# zips with no external tool (Python's zipfile is the fallback).
#
# 0.7.x published no wheels, so an explicit `--version=0.7.x` selects its
# legacy archive instead. Version-gating the legacy path ensures a DNS, TLS,
# or server failure for a modern wheel is surfaced instead of being mislabeled
# as a missing wheel and followed by a request for a nonexistent old archive.
case "$uname_s" in
    Linux*)  wheel_tag="manylinux_2_17_${arch}.manylinux2014_${arch}" ;;
    Darwin*) [[ "$arch" == "aarch64" ]] \
                 && wheel_tag="macosx_11_0_arm64" \
                 || wheel_tag="macosx_10_12_x86_64" ;;
    *)       [[ "$arch" == "aarch64" ]] \
                 && wheel_tag="win_arm64" \
                 || wheel_tag="win_amd64" ;;
esac

release="https://github.com/zackees/soldr/releases/download/v${VERSION}"
wheel_asset="soldr-${VERSION}-py3-none-${wheel_tag}.whl"
legacy_asset="soldr-v${VERSION}-${triple}.${ext}"

repo_root="$(cd "$(dirname "$0")" && pwd)"

if (( GLOBAL )); then
    if [[ -d "${HOME}/.cargo/bin" ]]; then
        target_dir="${HOME}/.cargo/bin"
    else
        target_dir="${HOME}/.local/bin"
        mkdir -p "$target_dir"
    fi
else
    if [[ -d "${repo_root}/.venv/Scripts" ]]; then
        target_dir="${repo_root}/.venv/Scripts"
    elif [[ -d "${repo_root}/.venv/bin" ]]; then
        target_dir="${repo_root}/.venv/bin"
    else
        echo "no .venv at ${repo_root}/.venv — run 'uv sync --group dev' first, or pass --global" >&2
        exit 1
    fi
fi

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT

unzip_to_tmp() {
    if command -v unzip >/dev/null 2>&1; then
        unzip -q "$1" -d "$tmp"
    elif [[ -x "$target_dir/python.exe" ]]; then
        "$target_dir/python.exe" -c \
            "import zipfile,sys; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])" \
            "$1" "$tmp"
    elif [[ -x "$target_dir/python" ]]; then
        "$target_dir/python" -c \
            "import zipfile,sys; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])" \
            "$1" "$tmp"
    elif command -v python3 >/dev/null 2>&1; then
        python3 -c \
            "import zipfile,sys; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])" \
            "$1" "$tmp"
    elif command -v python >/dev/null 2>&1; then
        python -c \
            "import zipfile,sys; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])" \
            "$1" "$tmp"
    else
        echo "cannot extract $1: install unzip or Python 3" >&2
        return 1
    fi
}

if [[ "$VERSION" == 0.7.* ]]; then
    echo "Downloading ${release}/${legacy_asset}"
    curl -fSL "${release}/${legacy_asset}" -o "$tmp/$legacy_asset"
    if [[ "$ext" == "zip" ]]; then
        unzip_to_tmp "$tmp/$legacy_asset"
    else
        tar -xzf "$tmp/$legacy_asset" -C "$tmp"
    fi
else
    echo "Downloading ${release}/${wheel_asset}"
    curl -fSL "${release}/${wheel_asset}" -o "$tmp/$wheel_asset"
    unzip_to_tmp "$tmp/$wheel_asset"
fi

src=$(find "$tmp" -type f -name "$binary" | head -n1)
if [[ -z "$src" ]]; then
    echo "binary $binary not found in the v${VERSION} download" >&2
    exit 1
fi

cp "$src" "$target_dir/$binary"
chmod +x "$target_dir/$binary"
echo "Installed soldr ${VERSION} -> $target_dir/$binary"
"$target_dir/$binary" --version
