#!/bin/bash
# FMSDesk installer for Intel and Apple-silicon Macs.
# Downloads the matching FMSPOS build, verifies its pinned digest and bundle
# identity, then installs it without embedding credentials or a password.

set -euo pipefail

readonly FMSDESK_VERSION="1.4.9-fmspos.1"
readonly DOWNLOAD_BASE="https://sos.fmspos.com/downloads"
readonly ID_SERVER="sos.fmspos.com"
readonly API_SERVER="https://sos.fmspos.com"
readonly PUBLIC_KEY="OETQPGXO0XCEqFiZN5accYIz9e5TxGKJTvUQiMNLqkk="
readonly SERVER_CONFIG="host=${ID_SERVER},key=${PUBLIC_KEY},api=${API_SERVER},"
readonly BUNDLE_ID="com.fmspos.fmsdesk"
readonly APPLICATION="/Applications/FMSDesk.app"

info() { printf '\n\033[1;32m%s\033[0m\n' "$*"; }
fail() { printf '\nFMSDesk installer error: %s\n' "$*" >&2; exit 1; }

if [[ "${1:-}" == "--help" ]]; then
  cat <<'HELP'
FMSDesk macOS installer

Usage:
  bash FMSPOS-RustDesk-macOS.sh

Supported:
  Intel Macs running macOS 10.14 or later
  Apple-silicon Macs running macOS 12.3 or later

This internal preview is not Developer ID signed or Apple notarized. The
installer verifies the architecture-specific SHA-256 and the app's ad-hoc code
signature before replacing any existing FMSDesk installation. Administrator
approval is required.

After installation, approve FMSDesk under:
  System Settings → Privacy & Security → Accessibility
  System Settings → Privacy & Security → Screen Recording
HELP
  exit 0
fi

[[ "$(uname -s)" == "Darwin" ]] || fail "This installer must be run on macOS."
for required_command in curl hdiutil shasum codesign lipo ditto; do
  command -v "${required_command}" >/dev/null 2>&1 \
    || fail "${required_command} is required to install FMSDesk."
done
[[ -x /usr/libexec/PlistBuddy ]] || fail "PlistBuddy is required to validate FMSDesk."

if (( EUID != 0 )); then
  command -v sudo >/dev/null 2>&1 || fail "sudo is required to install FMSDesk."
  info "Administrator approval is required to install FMSDesk."
  exec sudo -- /bin/bash "$0" "$@"
fi

if [[ "$(uname -m)" == "arm64" ]] \
  || [[ "$(sysctl -in hw.optional.arm64 2>/dev/null || true)" == "1" ]]; then
  architecture="Apple silicon"
  required_slice="arm64"
  asset="FMSDesk-${FMSDESK_VERSION}-macos-aarch64-unsigned.dmg"
  expected_sha256="eedccc697eb44addb33b2fa9927fb858b59f3258c51c36a74f699fec4f8c12f3"
else
  architecture="Intel"
  required_slice="x86_64"
  asset="FMSDesk-${FMSDESK_VERSION}-macos-x86_64-unsigned.dmg"
  expected_sha256="2f323a6ad6cb1b033ac15b3758e54124f3f900c0ed722f2ce2661bd25f473beb"
fi

tmp_dir="$(mktemp -d -t fmsdesk)"
dmg_path="${tmp_dir}/${asset}"
mount_point="${tmp_dir}/mounted"
candidate="/Applications/.FMSDesk-new-$$.app"
previous="/Applications/.FMSDesk-previous-$$.app"
mounted=0
rollback_needed=0

cleanup() {
  if (( mounted == 1 )); then
    hdiutil detach "${mount_point}" -quiet >/dev/null 2>&1 || true
  fi
  if (( rollback_needed == 1 )); then
    pkill -x FMSDesk >/dev/null 2>&1 || true
    rm -rf "${APPLICATION}"
    if [[ -e "${previous}" ]]; then
      mv "${previous}" "${APPLICATION}"
    fi
  else
    rm -rf "${previous}"
  fi
  rm -rf "${candidate}" "${tmp_dir}"
}
trap cleanup EXIT
trap 'exit 130' HUP INT TERM

mkdir -p "${mount_point}"
info "Downloading FMSDesk ${FMSDESK_VERSION} for ${architecture}"
curl --fail --location --proto '=https' --tlsv1.2 --retry 3 \
  --output "${dmg_path}" "${DOWNLOAD_BASE}/${asset}"

actual_sha256="$(shasum -a 256 "${dmg_path}" | awk '{print $1}')"
[[ "${actual_sha256}" == "${expected_sha256}" ]] \
  || fail "The downloaded DMG failed SHA-256 verification. Nothing was installed."
info "Published package checksum verified"

hdiutil attach "${dmg_path}" -nobrowse -readonly -mountpoint "${mount_point}" -quiet
mounted=1
source_app="$(find "${mount_point}" -maxdepth 2 -type d -name FMSDesk.app -print -quit)"
[[ -n "${source_app}" ]] || fail "The verified DMG did not contain FMSDesk.app."

info_plist="${source_app}/Contents/Info.plist"
source_binary="${source_app}/Contents/MacOS/FMSDesk"
[[ -f "${info_plist}" && -x "${source_binary}" ]] \
  || fail "The FMSDesk application bundle is incomplete."

actual_bundle_id="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "${info_plist}")"
[[ "${actual_bundle_id}" == "${BUNDLE_ID}" ]] \
  || fail "The application bundle identifier is not the expected FMSPOS identity."

binary_arches="$(lipo -archs "${source_binary}")"
case " ${binary_arches} " in
  *" ${required_slice} "*) ;;
  *) fail "The application does not contain the required ${required_slice} executable." ;;
esac

# Xcode gives unsigned local builds an ad-hoc signature. This checks bundle
# integrity only; it is deliberately not presented as Developer ID trust.
codesign --verify --deep --strict --verbose=2 "${source_app}"
info "FMSDesk bundle identity, architecture, and internal integrity verified"

pkill -x FMSDesk >/dev/null 2>&1 || true
sleep 1
ditto --rsrc --extattr "${source_app}" "${candidate}"
codesign --verify --deep --strict --verbose=2 "${candidate}"

if [[ -e "${APPLICATION}" ]]; then
  mv "${APPLICATION}" "${previous}"
fi
rollback_needed=1
mv "${candidate}" "${APPLICATION}"

readonly fmsdesk_binary="${APPLICATION}/Contents/MacOS/FMSDesk"
console_user="$(stat -f '%Su' /dev/console 2>/dev/null || true)"
[[ -n "${console_user}" && "${console_user}" != "root" && "${console_user}" != "loginwindow" ]] \
  || fail "Sign in to the Mac desktop before running this installer."
console_uid="$(id -u "${console_user}")"

info "Applying the trusted FMSPOS server identity"
launchctl asuser "${console_uid}" sudo -u "${console_user}" open "${APPLICATION}" \
  >/dev/null 2>&1 || fail "FMSDesk could not be opened for ${console_user}."

configured=0
for (( attempt=1; attempt<=10; attempt++ )); do
  sleep 1
  "${fmsdesk_binary}" --config "${SERVER_CONFIG}" >/dev/null 2>&1 || true
  configured_host="$("${fmsdesk_binary}" --option custom-rendezvous-server 2>/dev/null | tail -n 1 || true)"
  configured_api="$("${fmsdesk_binary}" --option api-server 2>/dev/null | tail -n 1 || true)"
  configured_key="$("${fmsdesk_binary}" --option key 2>/dev/null | tail -n 1 || true)"
  if [[ "${configured_host}" == "${ID_SERVER}" \
    && "${configured_api}" == "${API_SERVER}" \
    && "${configured_key}" == "${PUBLIC_KEY}" ]]; then
    configured=1
    break
  fi
done
(( configured == 1 )) || fail "FMSDesk did not retain the FMSPOS server identity."

rollback_needed=0
rm -rf "${previous}"

info "FMSDesk is installed and configured"
printf '%s\n' \
  "FMSDesk has been opened from Applications." \
  "Approve Accessibility and Screen Recording when macOS prompts you." \
  "This preview is unsigned; if macOS blocks its first launch, use" \
  "System Settings → Privacy & Security → Open Anyway." \
  "Wait for Ready, then share the displayed ID and one-time password with FMSPOS support."
