#!/usr/bin/env bash
#
# Installation de private-server sur Ubuntu/Debian (root requis).
#
# Prérequis : soit (a) le monorepo est présent avec le package déjà buildé
# (`pnpm build` dans apps/private-server) et ses dépendances installées —
# c'est le flux de déploiement habituel (scp du monorepo + build sur la
# machine) ; soit (b) une archive pré-construite (dossier d'installation
# avec dist/, node_modules réels et packaging/ à côté) : dans ce cas le
# `pnpm deploy` est inutile et pnpm n'est pas requis.
# Le script copie le package dans /opt/private-server et installe l'unité
# systemd + Caddy (reverse proxy HTTPS automatique).
#
# Usage :
#   ./install.sh --domain photos.exemple.fr \
#                --admin-email moi@exemple.fr \
#                [--admin-password <mdp>]     # sinon : mot de passe généré + affiché
#                [--family "Ma famille"]
#                [--app-dir /opt/private-server]
#                [--data-dir /var/lib/private-server]
#                [--no-caddy]                 # ne pas installer Caddy
#
# Sortie : récapitulatif final (URL, identifiants, état des services).

set -euo pipefail

# ----------------------------------------------------------------------
# Arguments
# ----------------------------------------------------------------------

DOMAIN=""
ADMIN_EMAIL=""
ADMIN_PASSWORD=""
FAMILY="Ma famille"
APP_DIR="/opt/private-server"
DATA_DIR="/var/lib/private-server"
WITH_CADDY=1

while [[ $# -gt 0 ]]; do
  case "$1" in
    --domain) DOMAIN="$2"; shift 2 ;;
    --admin-email) ADMIN_EMAIL="$2"; shift 2 ;;
    --admin-password) ADMIN_PASSWORD="$2"; shift 2 ;;
    --family) FAMILY="$2"; shift 2 ;;
    --app-dir) APP_DIR="$2"; shift 2 ;;
    --data-dir) DATA_DIR="$2"; shift 2 ;;
    --no-caddy) WITH_CADDY=0; shift ;;
    *) echo "Option inconnue : $1" >&2; exit 1 ;;
  esac
done

if [[ -z "$DOMAIN" || -z "$ADMIN_EMAIL" ]]; then
  echo "Usage : $0 --domain <domaine> --admin-email <email> [options]" >&2
  exit 1
fi

if [[ $EUID -ne 0 ]]; then
  echo "À exécuter en root (sudo)." >&2
  exit 1
fi

# ----------------------------------------------------------------------
# Prérequis : Node 24 + pnpm (pnpm seulement hors archive pré-construite)
# ----------------------------------------------------------------------

if ! command -v node >/dev/null 2>&1 || [[ "$(node -p 'process.versions.node.split(".")[0]')" -lt 24 ]]; then
  echo "Node 24 requis (node -v). Installez-le via nodesource :"
  echo "  curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && apt-get install -y nodejs"
  exit 1
fi

# ----------------------------------------------------------------------
# Sources du package (dossier du monorepo contenant apps/private-server,
# ou dossier d'archive pré-construite)
# ----------------------------------------------------------------------

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PKG_SRC="$(cd "$SCRIPT_DIR/../.." && pwd)"   # apps/private-server (ou racine de l'archive)

if [[ ! -f "$PKG_SRC/dist/index.js" ]]; then
  echo "Build absent : exécutez « pnpm build » dans $PKG_SRC d'abord." >&2
  exit 1
fi

# Archive pré-construite : node_modules RÉELS (répertoires, pas des symlinks
# workspace pnpm) déjà à côté de dist/ → copie directe, pas de pnpm deploy.
ARCHIVE_MODE=0
if [[ -d "$PKG_SRC/node_modules/@familyalbum/shared" && ! -L "$PKG_SRC/node_modules/@familyalbum/shared" ]]; then
  ARCHIVE_MODE=1
fi
if [[ "$ARCHIVE_MODE" -eq 0 ]] && ! command -v pnpm >/dev/null 2>&1; then
  echo "pnpm requis (npm i -g pnpm) — sauf à utiliser l'archive pré-construite." >&2
  exit 1
fi

# ----------------------------------------------------------------------
# Utilisateur système + dossiers
# ----------------------------------------------------------------------

echo "→ Utilisateur système + dossiers"
if ! id private-server >/dev/null 2>&1; then
  useradd --system --home "$DATA_DIR" --shell /usr/sbin/nologin private-server
fi
install -d -o private-server -g private-server "$DATA_DIR"
install -d -o root -g root "$APP_DIR"

# Déploiement du package (dépendances réelles via pnpm deploy).
# pnpm deploy crée un dossier autonome : node_modules réels, pas de symlinks.
# En mode archive, le dossier est déjà autonome : copie directe, sans trap
# (surtout ne PAS supprimer le dossier d'installation de l'utilisateur).
if [[ "$ARCHIVE_MODE" -eq 1 ]]; then
  echo "→ Archive pré-construite détectée — copie directe (pas de pnpm deploy)"
  SRC="$PKG_SRC"
else
  STAGE="$(mktemp -d)"
  trap 'rm -rf "$STAGE"' EXIT
  echo "→ Déploiement du package ($PKG_SRC)"
  (
    cd "$PKG_SRC"
    pnpm deploy --prod "$STAGE"
  )
  SRC="$STAGE"
fi
cp -r "$SRC"/. "$APP_DIR"/
rm -rf "$APP_DIR/data" "$APP_DIR/data-test"   # jamais de données de dev en prod

# ----------------------------------------------------------------------
# Fichier d'environnement
# ----------------------------------------------------------------------

echo "→ Configuration (/etc/private-server/env)"
install -d -o root -g root /etc/private-server
cat > /etc/private-server/env <<EOF
NODE_ENV=production
PORT=4100
DATA_DIR=$DATA_DIR
LOG_LEVEL=info
EOF
# Un mot de passe aléatoire est généré par l'assistant si non fourni.

# ----------------------------------------------------------------------
# Unité systemd
# ----------------------------------------------------------------------

echo "→ Unité systemd"
UNIT_TMP="$STAGE/private-server.service"
sed "s|__DATA_DIR__|$DATA_DIR|g" "$SCRIPT_DIR/private-server.service" > "$UNIT_TMP"
install -o root -g root -m 644 "$UNIT_TMP" /etc/systemd/system/private-server.service
systemctl daemon-reload
systemctl enable --now private-server

# ----------------------------------------------------------------------
# Caddy (HTTPS automatique Let's Encrypt)
# ----------------------------------------------------------------------

if [[ "$WITH_CADDY" -eq 1 ]]; then
  if ! command -v caddy >/dev/null 2>&1; then
    echo "→ Installation de Caddy (repo officiel)"
    apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
    apt-get update
    apt-get install -y caddy
  fi
  cat > /etc/caddy/Caddyfile <<EOF
$DOMAIN {
	encode zstd gzip
	reverse_proxy 127.0.0.1:4100
}
EOF
  systemctl reload caddy || systemctl restart caddy
  echo "→ Caddy : Caddyfile écrit et service rechargé (certificat HTTPS au premier accès)."
  echo "  ⚠  Pensez à pointer le DNS :  A  $DOMAIN  →  <IP de cette machine>"
else
  echo "→ Caddy ignoré (--no-caddy) : accès direct http://IP:4100"
fi

# ----------------------------------------------------------------------
# Assistant de premier lancement (compte admin + famille)
# ----------------------------------------------------------------------

if [[ -z "$ADMIN_PASSWORD" ]]; then
  ADMIN_PASSWORD="$(head -c 16 /dev/urandom | base64 | tr -d '+/=' | head -c 16)"
  GENERATED=1
fi

SETUP_ARGS=(setup --domain "$DOMAIN" --email "$ADMIN_EMAIL"
            --password "$ADMIN_PASSWORD" --family "$FAMILY" --yes --no-caddy)
sudo -u private-server -H env DATA_DIR="$DATA_DIR" node "$APP_DIR/dist/cli.js" "${SETUP_ARGS[@]}"

# ----------------------------------------------------------------------
# Récapitulatif
# ----------------------------------------------------------------------

echo
echo "════════════════════════════════════════════════════════════"
echo "  private-server installé"
echo
echo "  URL            https://$DOMAIN"
echo "  Identifiant    $ADMIN_EMAIL"
echo "  Mot de passe   $ADMIN_PASSWORD   ${GENERATED:+ (généré — à changer via reset-admin-password)}"
echo "  Famille        $FAMILY"
echo
echo "  Service        systemctl status private-server"
echo "  Logs           journalctl -u private-server -f"
echo "  Données        $DATA_DIR"
echo "════════════════════════════════════════════════════════════"
