#!/bin/bash
# Standalone installer for tektii-cli via get.tektii.com.
#
# Recommended usage (inspect before running):
#   curl -sSL https://get.tektii.com/install.sh -o install.sh && less install.sh && bash install.sh
#
# Quick install:
#   curl -sSL https://get.tektii.com/install.sh | bash
#
# Env overrides:
#   TEKTII_DOWNLOAD_URL  — base URL for downloads (default: https://get.tektii.com/download/latest)
#   TEKTII_INSTALL_DIR   — install directory (default: ~/.local/bin)
#
# Pin to a specific version:
#   TEKTII_DOWNLOAD_URL=https://get.tektii.com/download/tektii-cli-v0.2.0 \
#     curl -sSL https://get.tektii.com/install.sh | bash

set -euo pipefail

# Everything is wrapped in main() so a partially-downloaded script cannot
# execute a truncated install sequence when piped to bash. Bash buffers until
# the closing brace of main() before executing anything inside it.
main() {
    local base_url install_dir target archive archive_url checksum_url

    # Both the install dir and the shell startup file are derived from $HOME.
    [ -n "${HOME:-}" ] || err "HOME is not set — cannot determine where to install tektii"

    base_url="${TEKTII_DOWNLOAD_URL:-https://get.tektii.com/download/latest}"
    # ~/.local/bin is the conventional user-binary dir: on PATH by default in
    # most fresh Linux shells, and far less surprising than ~/.cargo/bin (which
    # is only on PATH when a Rust toolchain is set up). Where it is not on PATH
    # (e.g. a stock macOS shell), ensure_on_path below persists it to the user's
    # shell startup file so a new terminal still finds `tektii`.
    install_dir="${TEKTII_INSTALL_DIR:-$HOME/.local/bin}"

    target="$(detect_target)"
    archive="tektii-cli-${target}.tar.xz"
    archive_url="${base_url}/${archive}"
    checksum_url="${archive_url}.sha256"

    say "Detected target: ${target}"
    say "Downloading ${archive}..."

    tmp_dir=""
    trap '[ -n "${tmp_dir:-}" ] && rm -rf "${tmp_dir}"' EXIT
    tmp_dir="$(mktemp -d 2>/dev/null || mktemp -d -t 'tektii-install')"

    download "${archive_url}"      "${tmp_dir}/${archive}"
    download "${checksum_url}"     "${tmp_dir}/${archive}.sha256"

    say "Verifying checksum..."
    verify_checksum "${tmp_dir}" "${archive}"

    say "Extracting..."
    mkdir -p "${tmp_dir}/extracted"
    # cargo-dist archives have a single top-level directory: strip it.
    tar -xJf "${tmp_dir}/${archive}" --strip-components=1 -C "${tmp_dir}/extracted"

    if [ ! -f "${tmp_dir}/extracted/tektii" ]; then
        err "Archive did not contain expected 'tektii' binary"
    fi

    say "Installing to ${install_dir}..."
    mkdir -p "${install_dir}"
    # Only copy the binary itself — never trust other files from the archive.
    cp "${tmp_dir}/extracted/tektii" "${install_dir}/tektii"
    chmod +x "${install_dir}/tektii"

    # Make sure install_dir is on PATH so `tektii` resolves in a new shell with
    # no manual edit — notably on macOS, where ~/.local/bin is not on PATH by
    # default. ensure_on_path also exports it into the current shell so the
    # check below reflects the install.
    ensure_on_path "${install_dir}"

    if command -v tektii >/dev/null 2>&1 && [ "$(command -v tektii)" = "${install_dir}/tektii" ]; then
        say "Installed $(tektii --version 2>/dev/null || echo tektii) to ${install_dir}"
        say "Restart your shell (or run 'source $(profile_file)') if a new terminal can't find tektii."
    else
        say "Installed tektii to ${install_dir}"
        say ""
        say "Add it to your PATH for this session:"
        say "  export PATH=\"${install_dir}:\$PATH\""
    fi
}

# Print the shell startup file most likely to be sourced by the user's shell,
# so a persisted PATH export actually takes effect in new terminals.
profile_file() {
    case "$(basename "${SHELL:-/bin/sh}")" in
        zsh) echo "${ZDOTDIR:-$HOME}/.zshrc" ;;
        bash)
            # macOS Terminal starts bash as a login shell (~/.bash_profile);
            # most Linux interactive shells read ~/.bashrc.
            if [ "$(uname -s)" = "Darwin" ]; then
                echo "${HOME}/.bash_profile"
            else
                echo "${HOME}/.bashrc"
            fi
            ;;
        *) echo "${HOME}/.profile" ;;
    esac
}

# Ensure $1 is on PATH: no-op if already present, otherwise persist an export
# line to the user's shell startup file (idempotently) and add it to the
# current shell so the rest of this run sees it.
ensure_on_path() {
    local dir="$1" rc line
    case ":${PATH}:" in
        *":${dir}:"*) return 0 ;;
    esac

    rc="$(profile_file)"
    line="export PATH=\"${dir}:\$PATH\""
    if ! { [ -f "${rc}" ] && grep -qsF "${line}" "${rc}"; }; then
        printf '\n# Added by the tektii-cli installer\n%s\n' "${line}" >>"${rc}"
        say "Added ${dir} to your PATH in ${rc}."
    fi

    export PATH="${dir}:${PATH}"
}

say() {
    printf 'tektii-cli: %s\n' "$*"
}

err() {
    say "ERROR: $*" >&2
    exit 1
}

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

    case "${os}" in
        Linux)
            case "${arch}" in
                x86_64 | amd64)  echo "x86_64-unknown-linux-gnu"  ;;
                aarch64 | arm64) echo "aarch64-unknown-linux-gnu" ;;
                *) err "Unsupported Linux architecture: ${arch}" ;;
            esac
            ;;
        Darwin)
            case "${arch}" in
                x86_64 | amd64)  echo "x86_64-apple-darwin"  ;;
                aarch64 | arm64) echo "aarch64-apple-darwin" ;;
                *) err "Unsupported macOS architecture: ${arch}" ;;
            esac
            ;;
        *)
            err "Unsupported OS: ${os}. See https://get.tektii.com/download/latest/ for direct downloads."
            ;;
    esac
}

download() {
    local url="$1" out="$2"
    # --proto '=https' and --tlsv1.2 enforce a modern TLS connection and refuse any
    # downgrade to http/ftp even if the URL or a redirect tries to switch protocols.
    if ! curl --proto '=https' --tlsv1.2 -sSfL "${url}" -o "${out}"; then
        err "Failed to download ${url}"
    fi
}

verify_checksum() {
    local dir="$1" file="$2"
    # macOS ships shasum, most Linux distros ship sha256sum. Both understand the
    # cargo-dist checksum file format ("<hash>  <filename>").
    if command -v sha256sum >/dev/null 2>&1; then
        (cd "${dir}" && sha256sum -c "${file}.sha256") \
            || err "Checksum verification failed for ${file}"
    elif command -v shasum >/dev/null 2>&1; then
        (cd "${dir}" && shasum -a 256 -c "${file}.sha256") \
            || err "Checksum verification failed for ${file}"
    else
        err "No SHA256 tool found (need 'sha256sum' or 'shasum')"
    fi
}

# Run the installer unless it is being sourced (e.g. by tests) with
# TEKTII_INSTALL_SH_NO_MAIN set. main() is still the final statement, so a
# `curl | bash` pipe still buffers the whole script before executing anything.
if [ -z "${TEKTII_INSTALL_SH_NO_MAIN:-}" ]; then
    main "$@"
fi
