#!/bin/sh
# Install a self-hosted Ciele.
#
#   curl -fsSL <origin>/install.sh | sh
#   curl -fsSL <origin>/install.sh | sh -s -- --seed
#
# Fetches the source, then hands off to deploy/bootstrap.sh, which
# generates every secret and starts the stack. Arguments after `-s --` are
# forwarded to it (--seed, --env-only, --images).
#
# A Mac without Docker is not an error: the script fetches Ciele Desktop
# (or opens it if already installed) and the app guides the rest, Docker
# install included.
#
# Environment:
#   CIELE_DIR   where to put the checkout (default: ./ciele)
#   CIELE_REF   a release tag to install instead of the default branch
#
# Generated by apps/web/src/lib/self-host-install.ts, do not edit by hand.
set -eu

REPO="https://github.com/MattiaIppoliti/ciele"
DIR="${CIELE_DIR:-ciele}"
REF="${CIELE_REF:-}"

say() { printf '%s\n' "$*"; }
die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
have() { command -v "$1" >/dev/null 2>&1; }

OS="$(uname -s 2>/dev/null || echo unknown)"
case "$OS" in
  Darwin | Linux) ;;
  MINGW* | MSYS* | CYGWIN*)
    die "Windows shells cannot run this installer. Use Ciele Desktop, or run it inside WSL2."
    ;;
  *) die "Unsupported operating system, self-hosting is supported on macOS and Linux." ;;
esac

for cmd in bash openssl; do
  have "$cmd" || die "'$cmd' is required but not installed."
done

# Docker is the stack itself, so on Linux its absence is a refusal. A Mac
# gets handed to Ciele Desktop instead: the app's guided setup links Docker
# Desktop, re-checks in place, and stands up the same compose stack
# bootstrap.sh would, no terminal needed from there on.
if ! have docker; then
  [ "$OS" = "Darwin" ] ||
    die "'docker' is required but not installed."

  say "Docker is not installed. Handing you to Ciele Desktop instead, the"
  say "app walks you through installing Docker and sets up the stack itself."

  for app in "/Applications/Ciele.app" "$HOME/Applications/Ciele.app"; do
    if [ -d "$app" ]; then
      say "Ciele Desktop is already installed, opening it."
      open "$app" 2>/dev/null || say "Open $app from Finder to continue."
      exit 0
    fi
  done

  # The download needs the GitHub releases API; a fork hosted elsewhere gets
  # the plain refusal with both ways forward spelled out.
  case "$REPO" in
    https://github.com/*) ;;
    *) die "'docker' is required but not installed. Install Docker Desktop and re-run, or set up without a terminal using Ciele Desktop: $REPO/releases" ;;
  esac

  assets="$(curl -fsSL "https://api.github.com/repos/${REPO#https://github.com/}/releases/latest" |
    grep -o '"browser_download_url": *"[^"]*-mac.zip"' | cut -d'"' -f4 || true)"
  case "$(uname -m)" in
    arm64) app_zip="$(printf '%s
' "$assets" | grep arm64 | head -n 1 || true)" ;;
    *) app_zip="$(printf '%s
' "$assets" | grep -v arm64 | head -n 1 || true)" ;;
  esac
  [ -n "$app_zip" ] ||
    die "No Ciele Desktop download found. Install Docker Desktop and re-run, or get the app from $REPO/releases/latest"

  say "Downloading $app_zip…"
  tmp="$(mktemp -d)"
  curl -fSL --progress-bar "$app_zip" -o "$tmp/Ciele.app.zip"
  mkdir -p "$HOME/Applications"
  # ditto is macOS's own unarchiver; it keeps the .app bundle intact.
  ditto -x -k "$tmp/Ciele.app.zip" "$HOME/Applications"

  say ""
  say "Ciele Desktop is in $HOME/Applications, opening it now. It takes over"
  say "from here: install Docker when it asks, and it starts the stack itself."
  say "If macOS blocks the first open, right-click Ciele.app and choose Open."
  open "$HOME/Applications/Ciele.app" 2>/dev/null ||
    say "Open it from Finder to continue."
  exit 0
fi

# Compose ships as a docker plugin or as a standalone binary; bootstrap.sh
# accepts either, so accept either here too rather than rejecting a working
# machine.
if ! docker compose version >/dev/null 2>&1 && ! have docker-compose; then
  die "Docker Compose is required (install Docker Desktop or the compose plugin)."
fi

if [ -e "$DIR" ]; then
  # Re-running bootstrap.sh over an existing checkout is safe by design, it
  # never overwrites an existing deploy/.env, so a Ciele checkout is a resume,
  # and anything else is left strictly alone.
  [ -f "$DIR/deploy/bootstrap.sh" ] ||
    die "'$DIR' already exists and is not a Ciele checkout. Move it, or set CIELE_DIR to another path."
  say "Reusing the existing checkout in $DIR."
else
  say "Fetching Ciele into $DIR…"
  if have git; then
    if [ -n "$REF" ]; then
      git clone --depth 1 --branch "$REF" "$REPO.git" "$DIR"
    else
      git clone --depth 1 "$REPO.git" "$DIR"
    fi
  elif have curl && have tar; then
    # No git: a release tarball carries the same tree. --strip-components drops
    # the archive's own top-level directory, whose name embeds the ref.
    if [ -n "$REF" ]; then
      archive="$REPO/archive/refs/tags/$REF.tar.gz"
    else
      archive="$REPO/archive/refs/heads/main.tar.gz"
    fi
    mkdir -p "$DIR"
    curl -fsSL "$archive" | tar -xz -C "$DIR" --strip-components=1
  else
    die "Fetching the source needs either 'git', or 'curl' and 'tar'."
  fi
fi

cd "$DIR"
[ -f "deploy/bootstrap.sh" ] || die "This checkout has no deploy/bootstrap.sh."

say ""
say "Handing off to deploy/bootstrap.sh, it generates every secret and starts the stack."
say ""
exec bash ./deploy/bootstrap.sh "$@"
