#!/usr/bin/env bash
# ---------------------------------------------------------------------------
# Garden Financial — one-line installer for macOS and Linux.
#
#   curl -fsSL https://downloads.gardens.ml/install.sh | bash
#
# Behaviour:
#   1. Detect OS + arch
#   2. Fetch manifest from downloads.gardens.ml/manifest.json
#   3. Download the matching artifact
#   4. Verify sha256
#   5. Install:
#        - macOS: mount .dmg, copy .app to /Applications, clear quarantine
#        - Linux: install .deb via apt OR drop AppImage into ~/.local/bin
#
# Quiet by default. Set GARDEN_VERBOSE=1 for noisy output, or
# GARDEN_PREFIX=/path to override the install dir. The installer uses the
# version and artifact selected by the fetched manifest; GARDEN_VERSION is not
# a version selector.
# ---------------------------------------------------------------------------
set -euo pipefail

REGISTRY="${GARDEN_REGISTRY:-https://downloads.gardens.ml}"
MANIFEST_URL="${REGISTRY}/manifest.json"
QUIET="${GARDEN_QUIET:-0}"

# ---- ANSI ------------------------------------------------------------------
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
  BOLD=$(printf '\033[1m'); DIM=$(printf '\033[2m'); RESET=$(printf '\033[0m')
  MOSS=$(printf '\033[38;5;28m'); AMBER=$(printf '\033[38;5;172m'); RED=$(printf '\033[38;5;160m')
else
  BOLD=""; DIM=""; RESET=""; MOSS=""; AMBER=""; RED=""
fi

say()  { [ "$QUIET" = "1" ] || printf '%s\n' "$*"; }
note() { [ "$QUIET" = "1" ] || printf '%s%s%s %s\n' "$DIM" "  ·" "$RESET" "$*"; }
ok()   { [ "$QUIET" = "1" ] || printf '%s%s%s %s\n' "$MOSS" "  ✓" "$RESET" "$*"; }
warn() { printf '%s%s%s %s\n' "$AMBER" "  !" "$RESET" "$*" >&2; }
die()  { printf '%s%s%s %s\n' "$RED" "  ✗" "$RESET" "$*" >&2; exit 1; }

# ---- Banner ----------------------------------------------------------------
say ""
say "  ${BOLD}garden${RESET}  ${DIM}— the financial operating system${RESET}"
say "  ${DIM}https://gardens.ml${RESET}"
say ""

# ---- Detect OS + arch ------------------------------------------------------
case "$(uname -s)" in
  Darwin) OS="macos"  ;;
  Linux)  OS="linux"  ;;
  *)      die "Unsupported operating system: $(uname -s). Garden runs on macOS and Linux. Windows users — see ${REGISTRY}/install.ps1." ;;
esac

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

note "Host:  ${OS} ${ARCH}"

# ---- Dep check -------------------------------------------------------------
need() { command -v "$1" >/dev/null 2>&1 || die "Missing dependency: $1. Install it and re-run."; }
need curl
need jq
if command -v shasum >/dev/null 2>&1 || command -v sha256sum >/dev/null 2>&1; then
  :
else
  die "Missing dependency: shasum or sha256sum. Install one and re-run."
fi

SHA() {
  if command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | awk '{print $1}'
  else                                       sha256sum    "$1" | awk '{print $1}'
  fi
}

# ---- Fetch manifest --------------------------------------------------------
note "Fetching manifest…"
manifest_tmp="$(mktemp -t garden-manifest.XXXXXX)"
artifact_tmp=""
cleanup() {
  rm -f "$manifest_tmp"
  if [ -n "$artifact_tmp" ]; then
    rm -rf "$artifact_tmp"
  fi
}
trap cleanup EXIT
curl -fsSL "$MANIFEST_URL" -o "$manifest_tmp" || die "Could not fetch ${MANIFEST_URL}"

if [ -n "${GARDEN_VERSION:-}" ]; then
  die "GARDEN_VERSION is not supported; this installer uses the fetched manifest version."
fi

VERSION="$(jq -r '.version // empty' < "$manifest_tmp")"
[ -n "$VERSION" ] || die "Manifest is missing a version field."

# Map OS+arch to a download key.
# manifest.platforms.macos.universal.{url, sha256}
# manifest.platforms.linux.aarch64.{url, sha256}
# manifest.platforms.linux.x86_64.{url, sha256}
key="platforms.${OS}.${ARCH}"
[ "$OS" = "macos" ] && key="platforms.macos.universal"

URL=$(jq -r ".${key}.url // empty" < "$manifest_tmp")
SHA256=$(jq -r ".${key}.sha256 // empty" < "$manifest_tmp")

[ -n "$URL" ]    || die "No download available for ${OS} ${ARCH}. Check ${REGISTRY}."
[ -n "$SHA256" ] || die "Manifest is missing a sha256 for ${OS} ${ARCH}."
case "$SHA256" in
  0000000000000000000000000000000000000000000000000000000000000000)
    die "No released artifact is available for ${OS} ${ARCH}."
    ;;
esac
[ "${#SHA256}" -eq 64 ] || die "Manifest has an invalid sha256 for ${OS} ${ARCH}."
case "$SHA256" in
  *[!0-9a-fA-F]*)
    die "Manifest has an invalid sha256 for ${OS} ${ARCH}."
    ;;
esac

note "Version: ${BOLD}${VERSION}${RESET}"
note "Asset:   ${URL##*/}"

# ---- Download --------------------------------------------------------------
artifact_tmp="$(mktemp -d -t garden-install.XXXXXX)"
filename="${URL##*/}"
out="${artifact_tmp}/${filename}"

note "Downloading…"
curl -fL --progress-bar "$URL" -o "$out"

# ---- Verify ----------------------------------------------------------------
note "Verifying…"
got="$(SHA "$out")"
if [ "$got" != "$SHA256" ]; then
  die "Checksum mismatch.
        expected: ${SHA256}
        got:      ${got}
        url:      ${URL}"
fi
ok "Checksum verified."

# ---- Install ---------------------------------------------------------------
install_macos_dmg() {
  local dmg="$1"
  local mountpoint="${artifact_tmp}/mount"
  mkdir -p "$mountpoint"
  hdiutil attach -nobrowse -readonly -mountpoint "$mountpoint" "$dmg" >/dev/null
  [ -d "$mountpoint" ] || die "Failed to mount DMG."
  local appname
  appname="$(/bin/ls "$mountpoint" | grep '\.app$' | head -n 1 || true)"
  [ -n "$appname" ] || { hdiutil detach -quiet "$mountpoint" || true; die "DMG contains no .app bundle."; }

  if [ -d "/Applications/${appname}" ]; then
    note "Replacing existing /Applications/${appname}"
    rm -rf "/Applications/${appname}"
  fi
  cp -R "${mountpoint}/${appname}" "/Applications/"
  hdiutil detach -quiet "$mountpoint" || true
  xattr -dr com.apple.quarantine "/Applications/${appname}" 2>/dev/null || true
  ok "Installed: /Applications/${appname}"
  note "Launch with:  open -a \"${appname%.app}\""
}

install_linux_deb() {
  local deb="$1"
  if command -v apt >/dev/null 2>&1 || command -v apt-get >/dev/null 2>&1; then
    note "Installing via apt (you may be prompted for sudo)…"
    sudo apt-get install -y "$deb" || sudo dpkg -i "$deb"
    ok "Installed."
    note "Launch with:  garden"
  else
    warn "apt not found. Drop the binary somewhere on your PATH yourself:"
    note "  $deb"
  fi
}

install_linux_appimage() {
  local img="$1"
  local target="${GARDEN_PREFIX:-$HOME/.local/bin}/garden"
  mkdir -p "$(dirname "$target")"
  cp "$img" "$target"
  chmod +x "$target"
  ok "Installed: ${target}"
  case ":$PATH:" in
    *":$(dirname "$target"):"*) ;;
    *) warn "$(dirname "$target") is not on \$PATH. Add it to your shell profile." ;;
  esac
  note "Launch with:  garden"
}

case "$OS" in
  macos)
    install_macos_dmg "$out"
    ;;
  linux)
    case "$filename" in
      *.deb)      install_linux_deb       "$out" ;;
      *.AppImage) install_linux_appimage  "$out" ;;
      *)          die "Unrecognised Linux artifact: $filename" ;;
    esac
    ;;
esac

say ""
say "  ${MOSS}${BOLD}Garden is installed.${RESET}  Next:  ${DIM}gardens.ml/desktop${RESET}"
say ""
