#!/bin/bash
# PromptPilot Voice — one-line installer for macOS (Apple Silicon).
#
# Usage:
#   curl -fsSL https://promptpilotai.in/install-voice.sh | bash
#
# What it does:
#   1. Downloads the latest .dmg
#   2. Verifies its SHA-256 against a hash pinned in this script
#   3. Mounts it, copies the .app to /Applications
#   4. Strips macOS's "downloaded from internet" quarantine flag so
#      Gatekeeper doesn't block the first launch
#   5. Opens the app
#
# Why curl-pipe-bash and not a notarized DMG: PromptPilot Voice ships
# pre-notarization while Apple Developer enrollment is in flight. Same
# install pattern as rustup, deno, bun, brew. Once notarization is
# complete, this script still works (notarized binaries don't need the
# quarantine strip) and we'll also offer a GUI download button.
#
# What you're trusting: this script (readable in full at
# https://promptpilotai.in/install-voice.sh — it's what you're piping)
# and the .dmg it fetches. The two are hosted on DIFFERENT origins — this
# script from promptpilotai.in (Vercel), the .dmg from Supabase Storage —
# and this script pins the .dmg's SHA-256 (see EXPECTED_SHA256 below), so
# tampering with the storage bucket alone cannot swap the installer
# without also altering this script.

set -euo pipefail

APP_NAME="PromptPilot Voice"
APP_BUNDLE="${APP_NAME}.app"
INSTALL_DIR="/Applications"
DMG_NAME="PromptPilot-Voice.dmg"
# Public Supabase Storage bucket — each release uploads its .dmg under
# this stable name, so this URL always serves the newest build.
DOWNLOAD_URL="https://vyvffpqlzotkudbzlbqj.supabase.co/storage/v1/object/public/downloads/voice/${DMG_NAME}"

# SHA-256 of the .dmg above. MUST be bumped in lockstep with every release
# (see docs/RELEASE.md → "Publishing the public download"). Because this
# script and the .dmg live on different origins, a bucket-only compromise
# can't match this value — the install aborts on mismatch.
EXPECTED_SHA256="269d4d0e07c59b2bfb66322f0048b8ba68e6fe8e1708fb7444fa8e3d21969b29"

# ── Pre-flight ────────────────────────────────────────────────────────
if [[ "$(uname)" != "Darwin" ]]; then
  echo "❌ PromptPilot Voice is macOS-only. (Detected: $(uname))" >&2
  exit 1
fi

if [[ "$(uname -m)" != "arm64" ]]; then
  echo "❌ Apple Silicon (M1+) required. Intel Macs not yet supported." >&2
  echo "   Detected: $(uname -m)" >&2
  exit 1
fi

# Bail early if /Applications isn't writable — better than failing
# halfway through the install.
if [[ ! -w "${INSTALL_DIR}" ]]; then
  echo "❌ Can't write to ${INSTALL_DIR}. Re-run with sudo, or grant your" >&2
  echo "   user write access to /Applications." >&2
  exit 1
fi

# ── Stop any running instance so we can overwrite cleanly ────────────
if pgrep -x "promptpilot-voice" >/dev/null 2>&1; then
  echo "ℹ️  Quitting running PromptPilot Voice…"
  pkill -x "promptpilot-voice" 2>/dev/null || true
  # Give it a moment to release file handles
  sleep 1
fi

# ── Detach any leftover mount from a previous failed run ─────────────
if [[ -d "/Volumes/${APP_NAME}" ]]; then
  hdiutil detach "/Volumes/${APP_NAME}" -force >/dev/null 2>&1 || true
fi

# ── Set up temp workspace + cleanup trap ─────────────────────────────
TMPDIR=$(mktemp -d -t ppv-install)
trap 'rm -rf "${TMPDIR}"; hdiutil detach "/Volumes/${APP_NAME}" -force >/dev/null 2>&1 || true' EXIT

# ── Download ─────────────────────────────────────────────────────────
echo "📥 Downloading ${APP_NAME}…"
if ! curl -fL --progress-bar -o "${TMPDIR}/${DMG_NAME}" "${DOWNLOAD_URL}"; then
  echo "" >&2
  echo "❌ Download failed. Possible causes:" >&2
  echo "   • No internet connection" >&2
  echo "   • The latest release doesn't have an asset named ${DMG_NAME}" >&2
  echo "     (help: https://promptpilotai.in/voice)" >&2
  exit 1
fi

# ── Verify integrity ─────────────────────────────────────────────────
# Compare the download against the pinned hash BEFORE mounting or running
# anything from it. `shasum -a 256` ships with macOS by default.
echo "🔎 Verifying download…"
ACTUAL_SHA256=$(shasum -a 256 "${TMPDIR}/${DMG_NAME}" | awk '{print $1}')
if [[ "${ACTUAL_SHA256}" != "${EXPECTED_SHA256}" ]]; then
  echo "" >&2
  echo "❌ Checksum mismatch — refusing to install." >&2
  echo "   expected: ${EXPECTED_SHA256}" >&2
  echo "   actual:   ${ACTUAL_SHA256}" >&2
  echo "" >&2
  echo "   This can happen briefly during a release if the download and this" >&2
  echo "   script are momentarily out of sync — wait a few minutes and re-run." >&2
  echo "   If it persists, DO NOT install: report it at" >&2
  echo "   https://promptpilotai.in/voice" >&2
  exit 1
fi

# ── Mount the .dmg ───────────────────────────────────────────────────
echo "📦 Mounting installer…"
if ! hdiutil attach "${TMPDIR}/${DMG_NAME}" -nobrowse -quiet; then
  echo "❌ Couldn't mount the .dmg. The download may be corrupt." >&2
  exit 1
fi

# ── Copy into /Applications ──────────────────────────────────────────
# `${var:?}` defends against an empty expansion that would turn `rm -rf`
# into `rm -rf /`. Both vars are hardcoded constants so this is
# theoretical, but the guard is cheap.
echo "📂 Installing to ${INSTALL_DIR}…"
if [[ -d "${INSTALL_DIR:?}/${APP_BUNDLE:?}" ]]; then
  rm -rf "${INSTALL_DIR:?}/${APP_BUNDLE:?}"
fi
cp -R "/Volumes/${APP_NAME}/${APP_BUNDLE}" "${INSTALL_DIR}/"

# ── Strip quarantine ─────────────────────────────────────────────────
# `com.apple.quarantine` is the one extended attribute Gatekeeper
# checks. Removing it lets the app open without the "Apple could not
# verify…" dialog. -r recursively cleans nested executables in the
# bundle (Tauri apps have a few).
echo "🔓 Clearing macOS quarantine flag…"
xattr -dr com.apple.quarantine "${INSTALL_DIR}/${APP_BUNDLE}" 2>/dev/null || true

# ── Launch ───────────────────────────────────────────────────────────
echo "🚀 Launching ${APP_NAME}…"
open "${INSTALL_DIR}/${APP_BUNDLE}"

# ── First-run instructions ───────────────────────────────────────────
cat <<'EOF'

✅ Installed.

First-launch permissions:
  • Microphone         — macOS prompts on your first dictation
  • Accessibility      — grant manually in System Settings → Privacy &
                         Security → Accessibility (needed for auto-paste
                         and the Fn key; the app's Settings → Permissions
                         has one-click shortcuts to the right pane)
  • Speech Recognition — optional, only if you enable on-device
                         transcription; also granted manually

Hotkeys:
  ⌘⇧Space — hold to dictate (most reliable)
  ⌥Space  — one-handed alternative, same reliability
  Fn      — alternative dictation key (requires Accessibility;
            best-effort in the background)
  ⌘⇧R     — toggle raw mode (no AI cleanup)

Need help? https://promptpilotai.in/voice

EOF
