#!/usr/bin/env bash
# Infinitoo — one-line installer for a new main server (Core + panel).
#
#   curl -fsSL https://get.infinitoocore.com | sudo bash -s -- --domain panel.example.com --email you@example.com
#
# Options:
#   --domain NAME    the panel's name (DNS must point here); HTTPS from Let's Encrypt
#   --email ADDR     contact for Let's Encrypt
#   --version X.Y.Z  a specific release (default: the latest published)
#
# It downloads the signed release from the Infinitoo channel, verifies the
# signature with the release key pinned below, then runs the release's own
# installer (which verifies it again). Ubuntu 26.04.
set -euo pipefail

CHANNEL=${INFINITOO_CHANNEL:-https://get.infinitoocore.com}

# Pinned release-signing public key (Ed25519). Rotating it requires a new installer.
RELEASE_PUBKEY='-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAoRR90xONEyi7tXsFsLiu8LHUXOVqt9hLbD2cxGBXBs4=
-----END PUBLIC KEY-----'

main() {
  local domain="" email="" version=""
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --domain)  domain=$2; shift 2 ;;
      --email)   email=$2; shift 2 ;;
      --version) version=${2#v}; shift 2 ;;
      -h|--help) sed -n '2,12p' "$0" 2>/dev/null || true; exit 0 ;;
      *) echo "unknown option: $1" >&2; exit 2 ;;
    esac
  done
  log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
  die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }

  [[ $EUID -eq 0 ]] || die "run as root: curl -fsSL $CHANNEL | sudo bash -s -- --domain … --email …"
  [[ -n $domain ]] || die "--domain is required (the panel's name; its DNS must point to this server)"
  [[ -n $email ]] || die "--email is required (Let's Encrypt contact)"
  if ! command -v curl >/dev/null || ! command -v openssl >/dev/null; then
    log "installing curl and openssl"
    apt-get update -qq && apt-get install -y -qq ca-certificates curl openssl tar >/dev/null
  fi
  case "$(uname -m)" in
    x86_64)  arch=amd64 ;;
    aarch64) arch=arm64 ;;
    *) die "unsupported architecture $(uname -m)" ;;
  esac
  if [[ -z $version ]]; then
    version=$(curl -fsSL "$CHANNEL/latest" | tr -d '[:space:]')
  fi
  [[ $version =~ ^[0-9][0-9A-Za-z.+-]*$ ]] || die "could not get a valid version from $CHANNEL/latest"

  work=$(mktemp -d)
  trap 'rm -rf "$work"' EXIT
  local base="$CHANNEL/releases/v$version"
  local core="infinitoo-core_${version}_linux_${arch}.tar.gz" edge="infinitoo-edge_${version}_linux_${arch}.tar.gz"
  log "downloading Infinitoo $version ($arch)"
  for f in "$core" "$edge" SHA256SUMS SHA256SUMS.sig; do
    curl -fsSL --retry 3 -o "$work/$f" "$base/$f" || die "download failed: $base/$f"
  done

  printf '%s\n' "$RELEASE_PUBKEY" > "$work/release.pub"
  openssl pkeyutl -verify -pubin -inkey "$work/release.pub" -rawin -in "$work/SHA256SUMS" -sigfile "$work/SHA256SUMS.sig" >/dev/null \
    || die "release signature verification FAILED: not installing"
  (cd "$work" && grep -E "[[:space:]]\*?(${core//./\\.}|${edge//./\\.})$" SHA256SUMS | sha256sum -c --status) \
    || die "checksum mismatch: not installing"
  log "signature and checksums OK"

  mkdir -p "$work/x"
  tar -xzf "$work/$core" -C "$work/x"
  installer=$(find "$work/x" -mindepth 2 -maxdepth 2 -name install.sh | head -1)
  [[ -n $installer ]] || die "release has no installer"
  bash "$installer" --from-file "$work/$core" --domain "$domain" --acme-email "$email" --update-channel "$CHANNEL"

  # Load balancers installed from the panel take the Edge release from Core.
  local dir
  dir=$(grep -E '^RELEASES_DIR=' /etc/infinitoo/core.env | cut -d= -f2-)
  dir=${dir:-/var/lib/infinitoo/core/releases}/v$version
  install -d -m 0750 -o infinitoo -g infinitoo "$dir"
  install -m 0640 -o infinitoo -g infinitoo "$work/$edge" "$work/SHA256SUMS" "$work/SHA256SUMS.sig" "$dir/"
  log "done: open https://$domain/admin/"
  # First run: the one-time code that creates the first admin in the browser.
  local code
  code=$(set -a; . /etc/infinitoo/core.env; set +a; /opt/infinitoo/bin/infinitoo-core setup-code 2>/dev/null || true)
  if [[ -n $code ]]; then
    log "setup code for the first admin: $code"
  fi
}

# Everything runs from main, so a partial download (curl | bash) does nothing.
main "$@"
