#!/bin/bash
#
# MyTechie RustDesk Auto-Installer (Linux)
# Version: 2.4.0
# RustDesk: 1.4.9
#

set -euo pipefail

installer_version="2.4.0"
rustdesk_version="1.4.9"
support_url="https://mytechie.com.au/remote/"
rustdesk_cfg="0nI9MnVR9Uc2I1dGVWNQRUZn1UU3Q0cQ1UV6NVUoljQkdUTWV0YZVWdhlnYShjI6ISeltmIsIyNxETMyoTdh5SbvNmLllGajVGd51mLlR3btVmciojI5FGblJnIsIiNxETMyoTdh5SbvNmLllGajVGd51mLlR3btVmciojI0N3boJye"
verify_only=0
workdir=""
failure_code=""

if [[ "${1:-}" == "--verify-only" ]]; then
    verify_only=1
elif [[ $# -gt 0 ]]; then
    echo "Unknown option: $1"
    exit 2
fi

step() {
    printf '[%s/5] %s\n' "$1" "$2"
}

fail() {
    failure_code="$1"
    printf '\nSetup failed (%s).\n%s\n' "$1" "$2" >&2
    printf 'Leave this window open and contact your MyTechie technician: %s\n' "$support_url" >&2
    exit 1
}

cleanup() {
    if [[ -n "$workdir" ]]; then
        rm -rf "$workdir"
    fi
}

on_exit() {
    status=$?
    cleanup
    if [[ $status -ne 0 && -z "$failure_code" ]]; then
        printf '\nSetup stopped unexpectedly. Leave this window open and contact your MyTechie technician: %s\n' "$support_url" >&2
    fi
    exit "$status"
}
trap on_exit EXIT

printf '\n=== MyTechie Remote Support Installer v%s (Linux) ===\n\n' "$installer_version"

if [[ $verify_only -eq 0 && $EUID -ne 0 ]]; then
    fail "LIN-ELEVATION" "Administrator access is required. Run: curl -fsSL https://mytechie.com.au/remote/linux.sh | sudo bash"
fi

if command -v apt-get >/dev/null 2>&1; then
    package_type="deb"
elif command -v dnf >/dev/null 2>&1; then
    package_type="rpm-dnf"
elif command -v yum >/dev/null 2>&1; then
    package_type="rpm-yum"
elif command -v zypper >/dev/null 2>&1; then
    package_type="rpm-suse"
elif command -v pacman >/dev/null 2>&1; then
    package_type="arch"
else
    fail "LIN-DISTRO" "Unsupported Linux distribution. Debian, Ubuntu, Raspberry Pi OS, Fedora, RHEL, openSUSE, and Arch are supported."
fi

case "$(uname -m)" in
    x86_64|amd64)
        architecture="x86_64"
        ;;
    aarch64|arm64)
        architecture="aarch64"
        ;;
    armv7l|armhf)
        architecture="armv7"
        ;;
    *)
        fail "LIN-ARCH" "Unsupported CPU architecture: $(uname -m)"
        ;;
esac

case "${package_type}:${architecture}" in
    deb:x86_64)
        asset="rustdesk-${rustdesk_version}-x86_64.deb"
        expected_sha256="7244ba47c40e804172044bfbe659467c54ce46554c98e78c8c0406f1d612fda3"
        ;;
    deb:aarch64)
        asset="rustdesk-${rustdesk_version}-aarch64.deb"
        expected_sha256="ce62c996f14d33f3bbe3a330e953644a44bace7f05885a7953f7395d69fb49c0"
        ;;
    deb:armv7)
        asset="rustdesk-${rustdesk_version}-armv7-sciter.deb"
        expected_sha256="7c5f602f2978963fe00d75d69ec141261f27ad27920740d7c37313c402c486c8"
        ;;
    rpm-dnf:x86_64|rpm-yum:x86_64)
        asset="rustdesk-${rustdesk_version}-0.x86_64.rpm"
        expected_sha256="eb1b053ac5b2f774f2271f7fbbfd2ea475899f7a55135c5e172bc54b9388f108"
        ;;
    rpm-dnf:aarch64|rpm-yum:aarch64)
        asset="rustdesk-${rustdesk_version}-0.aarch64.rpm"
        expected_sha256="3e523df7ceb6f3804b047a3cac797354c4bf46ec19f2d7ff5e198787003cb092"
        ;;
    rpm-suse:x86_64)
        asset="rustdesk-${rustdesk_version}-0.x86_64-suse.rpm"
        expected_sha256="b28bdb5a4afcd3f0475664ad2e635eb4209f15ed44566f83469453b175e8a197"
        ;;
    rpm-suse:aarch64)
        asset="rustdesk-${rustdesk_version}-0.aarch64-suse.rpm"
        expected_sha256="e426192be57357eb9178f886b92188d6839eeb438d64a206fcea9dfb49eaee59"
        ;;
    arch:x86_64)
        asset="rustdesk-${rustdesk_version}-0-x86_64.pkg.tar.zst"
        expected_sha256="679760e1a1f1b930529069edfaec219afa16b5efe44c1bc593cede0e65576c11"
        ;;
    *)
        fail "LIN-PACKAGE" "RustDesk does not publish a supported ${package_type} package for ${architecture}."
        ;;
esac

download_and_verify() {
    workdir=$(mktemp -d)
    chmod 700 "$workdir"
    package_path="$workdir/$asset"
    url="https://github.com/rustdesk/rustdesk/releases/download/${rustdesk_version}/${asset}"

    curl --fail --location --silent --show-error \
        --retry 3 --retry-delay 2 --connect-timeout 15 \
        --proto '=https' --tlsv1.2 \
        -H "User-Agent: MyTechie-RustDesk-Installer/${installer_version}" \
        "$url" -o "$package_path" ||
        fail "LIN-DOWNLOAD" "RustDesk could not be downloaded after three attempts."

    actual_sha256=$(sha256sum "$package_path" | awk '{print $1}')
    if [[ "$actual_sha256" != "$expected_sha256" ]]; then
        fail "LIN-INTEGRITY" "The RustDesk download did not match the approved SHA-256 digest."
    fi

    printf 'Verified RustDesk %s (%s).\n' "$rustdesk_version" "$asset"
}

if [[ $verify_only -eq 1 ]]; then
    step 1 "Checking the approved RustDesk package"
    download_and_verify
    printf 'Verification complete. No software was installed.\n'
    exit 0
fi

step 1 "Checking this Linux device"
printf 'Package family: %s\nArchitecture: %s\n' "$package_type" "$architecture"

if command -v rustdesk >/dev/null 2>&1; then
    rustdesk_bin=$(command -v rustdesk)
    printf 'RustDesk is already installed. The existing app will be configured.\n'
else
    step 2 "Downloading and verifying RustDesk $rustdesk_version"
    download_and_verify

    printf 'Installing RustDesk...\n'
    case "$package_type" in
        deb)
            apt-get update -qq
            DEBIAN_FRONTEND=noninteractive apt-get install -y "$package_path"
            ;;
        rpm-dnf)
            dnf install -y "$package_path"
            ;;
        rpm-yum)
            yum localinstall -y "$package_path"
            ;;
        rpm-suse)
            # RustDesk's SUSE RPM is unsigned; the pinned SHA-256 check above is
            # the release-integrity control for this exact approved package.
            zypper --non-interactive install --allow-unsigned-rpm "$package_path"
            ;;
        arch)
            pacman -U --noconfirm "$package_path"
            ;;
    esac

    rustdesk_bin=$(command -v rustdesk || true)
    [[ -n "$rustdesk_bin" ]] || fail "LIN-INSTALL" "RustDesk finished installing, but the rustdesk command could not be found."
fi

step 3 "Configuring the MyTechie relay and support password"
support_password=$(LC_ALL=C dd if=/dev/urandom bs=48 count=1 2>/dev/null |
    base64 | tr -dc 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789' |
    cut -c1-16)
"$rustdesk_bin" --config "$rustdesk_cfg" >/dev/null ||
    fail "LIN-CONFIG" "RustDesk rejected the MyTechie server configuration."
"$rustdesk_bin" --password "$support_password" >/dev/null ||
    fail "LIN-PASSWORD" "RustDesk could not set the support access password."

step 4 "Starting the RustDesk service"
command -v systemctl >/dev/null 2>&1 ||
    fail "LIN-SERVICE" "This installer requires a systemd-based Linux desktop."
systemctl enable rustdesk >/dev/null
systemctl restart rustdesk
systemctl is-active --quiet rustdesk ||
    fail "LIN-SERVICE" "The RustDesk service did not become active."

step 5 "Waiting for this device's RustDesk ID"
rustdesk_id=""
for attempt in $(seq 1 15); do
    rustdesk_id=$("$rustdesk_bin" --get-id 2>/dev/null | tr -cd '0-9' || true)
    if [[ ${#rustdesk_id} -ge 6 ]]; then
        break
    fi
    printf 'Waiting for registration... (%s/15)\n' "$attempt"
    sleep 2
done

if [[ ${#rustdesk_id} -lt 6 ]]; then
    fail "LIN-ID" "RustDesk is installed, but its ID is not ready. Open RustDesk from the application menu and tell your technician the ID shown there."
fi

printf '\n=========================================\n'
printf ' MyTechie Remote Support Setup Complete\n'
printf '=========================================\n\n'
printf 'RustDesk ID:      %s\n' "$rustdesk_id"
printf 'Access password:  %s\n\n' "$support_password"
printf 'Share these details only with your MyTechie technician.\n'
printf 'This password remains active until it is changed, the installer is rerun, or RustDesk is removed.\n'
printf 'You may now close this Terminal window.\n\n'
