#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

DEFAULT_RELEASE_BASE_URL="https://download.veyraforge.online/current"
RELEASE_BASE_URL="${VEYRA_RELEASE_BASE_URL:-$DEFAULT_RELEASE_BASE_URL}"

PINNED_RELEASE_PUBLIC_KEY_B64="LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUNvd0JRWURLMlZ3QXlFQUF2dm4rRVJKRG9ramhPRDhjbzJDaDN4bUNCUUxZbkNmQWhlcll6VUx2QVU9Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
PINNED_RELEASE_PUBLIC_KEY_FINGERPRINT="64ee0a89e581f352d7ed923709155e365d524935bf4c58b75180128c80d67160"

die() {
    echo "VEYRA INSTALL ERROR: $*" >&2
    exit 1
}

if [[ $EUID -ne 0 ]]; then
    die "run as root (example: curl -fsSL https://download.veyraforge.online | sudo bash)"
fi

case "$RELEASE_BASE_URL" in
    https://*)
        ;;
    *)
        die "release channel must use HTTPS: $RELEASE_BASE_URL"
        ;;
esac

command -v apt-get >/dev/null 2>&1 ||
    die "Ubuntu/Debian apt-get is required"

missing=()

for cmd in curl openssl sha256sum tar base64; do
    command -v "$cmd" >/dev/null 2>&1 || missing+=("$cmd")
done

if (( ${#missing[@]} > 0 )); then
    export DEBIAN_FRONTEND=noninteractive
    apt-get update -qq
    apt-get install -y -qq ca-certificates curl openssl coreutils tar >/dev/null
fi

TMP="$(mktemp -d /tmp/veyra-public-install.XXXXXX)"
cleanup() {
    rm -rf "$TMP"
}
trap cleanup EXIT

PUB="$TMP/release-signing.pub.pem"

printf '%s' "$PINNED_RELEASE_PUBLIC_KEY_B64" |
    base64 -d > "$PUB"

actual_fp="$(
    openssl pkey \
        -pubin \
        -in "$PUB" \
        -outform DER 2>/dev/null |
    sha256sum |
    awk '{print $1}'
)"

[[ "$actual_fp" == "$PINNED_RELEASE_PUBLIC_KEY_FINGERPRINT" ]] ||
    die "embedded release trust key fingerprint mismatch"

download() {
    local name="$1"
    local max_size

    case "$name" in
        VERSION|SHA256SUMS)
            max_size=4096
            ;;
        manifest.json|release.tar.gz.sig)
            max_size=65536
            ;;
        release.tar.gz)
            max_size=536870912
            ;;
        *)
            die "unexpected release file: $name"
            ;;
    esac

    curl \
        --fail \
        --silent \
        --show-error \
        --location \
        --proto '=https' \
        --proto-redir '=https' \
        --tlsv1.2 \
        --connect-timeout 10 \
        --max-time 300 \
        --max-filesize "$max_size" \
        --retry 2 \
        --retry-delay 1 \
        --output "$TMP/$name" \
        "${RELEASE_BASE_URL%/}/$name"

    [[ "$(stat -c '%s' "$TMP/$name")" -le "$max_size" ]] ||
        die "release file too large: $name"
}

echo
echo "========================================"
echo " VEYRA"
echo " Твоя сеть. Твои правила."
echo "========================================"
echo
echo "Получаю подписанный релиз…"

for f in VERSION SHA256SUMS manifest.json release.tar.gz release.tar.gz.sig; do
    download "$f"
done

[[ "$(wc -l < "$TMP/SHA256SUMS")" -eq 1 ]] ||
    die "SHA256SUMS must contain exactly one entry"

read -r sums_sha sums_name sums_extra <<< "$(
    tr -d '\r' < "$TMP/SHA256SUMS"
)"
sums_name="${sums_name#\*}"

[[ -z "${sums_extra:-}" &&
   "$sums_sha" =~ ^[0-9a-f]{64}$ &&
   "$sums_name" == "release.tar.gz" ]] ||
    die "invalid SHA256SUMS entry"

computed_sha="$(
    sha256sum "$TMP/release.tar.gz" |
    awk '{print $1}'
)"

[[ "$computed_sha" == "$sums_sha" ]] ||
    die "release SHA256 verification failed"

openssl pkeyutl \
    -verify \
    -pubin \
    -inkey "$PUB" \
    -rawin \
    -in "$TMP/release.tar.gz" \
    -sigfile "$TMP/release.tar.gz.sig" \
    >/dev/null ||
    die "release Ed25519 signature verification failed"

VERSION="$(tr -d '[:space:]' < "$TMP/VERSION")"

[[ "$VERSION" =~ ^[A-Za-z0-9._+-]+$ ]] ||
    die "invalid release version"

SHA="$computed_sha"

[[ "$SHA" =~ ^[0-9a-f]{64}$ ]] ||
    die "invalid release SHA256"

manifest_version="$(
    sed -nE 's/.*"version":"([^"]+)".*/\1/p' "$TMP/manifest.json"
)"

manifest_sha="$(
    sed -nE 's/.*"sha256":"([^"]+)".*/\1/p' "$TMP/manifest.json"
)"

manifest_artifact="$(
    sed -nE 's/.*"artifact":"([^"]+)".*/\1/p' "$TMP/manifest.json"
)"

[[ "$manifest_version" == "$VERSION" ]] ||
    die "manifest version mismatch"

[[ "$manifest_sha" == "$SHA" ]] ||
    die "manifest SHA256 mismatch"

[[ "$manifest_artifact" == "release.tar.gz" ]] ||
    die "unexpected manifest artifact"

mkdir "$TMP/release"
tar -xzf "$TMP/release.tar.gz" -C "$TMP/release"

ROOT="$(
    find "$TMP/release" \
        -mindepth 1 \
        -maxdepth 1 \
        -type d |
    sed -n '1p'
)"

[[ -n "$ROOT" ]] ||
    die "release archive root not found"

[[ -x "$ROOT/bin/veyra" ]] ||
    die "release does not contain Veyra TUI"

[[ -x "$ROOT/scripts/veyra-install-engine" ]] ||
    die "release does not contain install engine"

[[ -s "$ROOT/ARCH" ]] ||
    die "release architecture metadata missing"

case "$(uname -m)" in
    x86_64)
        host_arch=amd64
        ;;
    aarch64|arm64)
        host_arch=arm64
        ;;
    *)
        die "unsupported architecture: $(uname -m)"
        ;;
esac

release_arch="$(tr -d '[:space:]' < "$ROOT/ARCH")"

[[ "$host_arch" == "$release_arch" ]] ||
    die "release architecture mismatch: host=$host_arch release=$release_arch"

archive_version="$(tr -d '[:space:]' < "$ROOT/VERSION")"

[[ "$archive_version" == "$VERSION" ]] ||
    die "release archive VERSION mismatch"

echo "✓ SHA256"
echo "✓ Ed25519 signature"
echo "✓ $VERSION · $release_arch"
echo

export VEYRA_RELEASE_BASE_URL="$RELEASE_BASE_URL"
export VEYRA_RELEASE_PUBLIC_KEY="$PUB"
export VEYRA_RELEASE_PUBLIC_KEY_FINGERPRINT="$PINNED_RELEASE_PUBLIC_KEY_FINGERPRINT"

if [[ -r /dev/tty && -w /dev/tty ]]; then
    "$ROOT/bin/veyra" \
        install \
        --engine "$ROOT/scripts/veyra-install-engine" \
        </dev/tty
else
    die "interactive terminal is required"
fi
