#!/usr/bin/env bash
# One-shot installer for a fresh Ubuntu 24.04 server (e.g. a DigitalOcean Droplet).
# Run as root from the project folder, after copying the code and a filled-in .env:
#   cd /opt/rainciti && bash deploy/install.sh
# Safe to re-run: every step checks what is already in place.
set -euo pipefail

DOMAIN="${DOMAIN:-rainciti.com}"
APP_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$APP_DIR"

say() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; }
die() { printf '\n\033[1;31mError: %s\033[0m\n' "$*" >&2; exit 1; }

[ "$(id -u)" -eq 0 ] || die "run this as root (or with sudo)"
[ -f .env ] || die "no .env in $APP_DIR. Copy .env.example to .env and fill it in first."
grep -q '^APP_URL=https://' .env || die "set APP_URL=https://$DOMAIN in .env"
grep -Eq '^POSTGRES_PASSWORD=(change-me)?$' .env && die "set a strong POSTGRES_PASSWORD in .env"
grep -q '^MAIL_TRANSPORT=console' .env && echo "Warning: MAIL_TRANSPORT=console, so sign-in emails will only be logged."
for d in public/before public/after; do
  [ -e "$d" ] && echo "Warning: $d is on the server; it is not used by the site and can be deleted."
done

say "Installing Docker, Nginx, Certbot and the firewall"
export DEBIAN_FRONTEND=noninteractive
apt-get update -q
apt-get install -y -q docker.io docker-compose-v2 docker-buildx nginx certbot python3-certbot-nginx ufw
systemctl enable --now docker nginx

say "Opening ports 22, 80 and 443"
ufw allow OpenSSH >/dev/null
ufw allow 'Nginx Full' >/dev/null
ufw --force enable >/dev/null

say "Building and starting the app (first build takes a few minutes)"
docker compose up -d --build
for i in $(seq 1 60); do
  curl -fs -o /dev/null http://127.0.0.1:3000/ && break
  [ "$i" -eq 60 ] && { docker compose logs --tail=50 app; die "the app did not come up; logs above"; }
  sleep 2
done
echo "App is answering on 127.0.0.1:3000"

say "Configuring Nginx for $DOMAIN"
if [ ! -e /etc/nginx/sites-available/rainciti.conf ]; then
  sed "s/rainciti\.com/$DOMAIN/g" docker/nginx/rainciti.conf > /etc/nginx/sites-available/rainciti.conf
fi
ln -sf /etc/nginx/sites-available/rainciti.conf /etc/nginx/sites-enabled/rainciti.conf
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx

say "Getting the HTTPS certificate"
SERVER_IP="$(curl -fs4 https://api.ipify.org || true)"
DNS_IP="$(getent ahostsv4 "$DOMAIN" | awk 'NR==1{print $1}' || true)"
CERT_EMAIL="$(sed -n 's/^ADMIN_EMAIL=//p' .env | tr -d '"' | head -1)"
if [ -n "$SERVER_IP" ] && [ "$SERVER_IP" = "$DNS_IP" ]; then
  if [ -n "$CERT_EMAIL" ]; then EMAIL_ARG=(-m "$CERT_EMAIL"); else EMAIL_ARG=(--register-unsafely-without-email); fi
  certbot --nginx --redirect --hsts --non-interactive --agree-tos \
    "${EMAIL_ARG[@]}" -d "$DOMAIN" -d "www.$DOMAIN" \
    && echo "HTTPS is live at https://$DOMAIN" \
    || echo "Certbot failed (check that both $DOMAIN and www.$DOMAIN point here), then re-run this script."
else
  echo "Skipped: $DOMAIN points at '${DNS_IP:-nothing}', this server is '${SERVER_IP:-unknown}'."
  echo "Once the DNS A records point here, re-run: bash deploy/install.sh"
fi

say "Done"
cat <<EOF
Create (or reset) the admin login:
  docker compose exec -it -e ADMIN_EMAIL=you@example.com app node prisma/seed.mjs
Update after copying new code:
  docker compose up -d --build
Logs:
  docker compose logs -f app
EOF
