#!/usr/bin/env bash
# issue-letsencrypt.sh — issue per-name Let's Encrypt certificates via the OVH
# DNS-01 challenge (acme.sh) and install them where Caddy serves them.
#
# Run MANUALLY on the host. One separate certificate per name:
#   ${BASE_DOMAIN}  +  <sub>.${BASE_DOMAIN} for each sub in LE_SUBDOMAINS.
# Certs land in certs/<name>/{cert.pem,key.pem} (gitignored) and the host nginx
# is reloaded so it picks them up (see nginx/ulicraft.conf.tmpl).
#
# DNS-01 needs no inbound ports — works for a LAN-only host. It only needs OVH
# API credentials with DNS-record write access for the zone.
#
# .env vars required:
#   BASE_DOMAIN       e.g. ulicraft.net
#   LE_EMAIL          account email for Let's Encrypt
#   OVH_AK OVH_AS     OVH application key + secret
#   OVH_CK            OVH consumer key (obtained on first run — see below)
#   OVH_END_POINT     OVH API endpoint (e.g. ovh-eu)
# optional:
#   LE_SUBDOMAINS     space-separated (default: "auth pack distribution www avatar status")
#   LE_STAGING=1      use the LE staging CA (untrusted, for dry runs)
#
# First-time OVH consumer key: set OVH_AK/OVH_AS/OVH_END_POINT, leave OVH_CK
# empty, run this once — acme.sh prints an authorization URL. Visit it, grant
# access, then copy the consumer key it shows into OVH_CK in .env and re-run.
# (Or create a token directly: https://eu.api.ovh.com/createToken/ with
#  GET/POST/PUT/DELETE on /domain/zone/*.)
set -euo pipefail

cd "$(dirname "$0")/.."   # repo root

log()  { printf '\n\033[1;32m==>\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m!!\033[0m %s\n' "$*" >&2; }
die()  { printf '\033[1;31mxx\033[0m %s\n' "$*" >&2; exit 1; }

# ---- config / preflight ----------------------------------------------------
[ -f .env ] || die ".env not found (copy .env.example and fill it)"
# shellcheck disable=SC1091
set -a; . ./.env; set +a
: "${BASE_DOMAIN:?BASE_DOMAIN unset in .env}"
: "${LE_EMAIL:?LE_EMAIL unset in .env}"
: "${OVH_AK:?OVH_AK unset in .env}"
: "${OVH_AS:?OVH_AS unset in .env}"
: "${OVH_END_POINT:?OVH_END_POINT unset in .env (e.g. ovh-eu)}"
# OVH_CK may be empty on the very first run (acme.sh will print the auth URL).
export OVH_AK OVH_AS OVH_END_POINT
export OVH_CK="${OVH_CK:-}"

ACME="${ACME_SH:-$HOME/.acme.sh/acme.sh}"
[ -x "$ACME" ] || ACME="$(command -v acme.sh || true)"
[ -n "$ACME" ] && [ -x "$ACME" ] || die "acme.sh not found. Install:
  curl https://get.acme.sh | sh -s email=${LE_EMAIL}
then re-run (or set ACME_SH=/path/to/acme.sh)."

CERT_DIR="${CERT_DIR:-certs}"
read -r -a SUBDOMAINS <<< "${LE_SUBDOMAINS:-auth pack distribution www avatar status}"

if [ "${LE_STAGING:-0}" = "1" ]; then
  SERVER="letsencrypt_test"; warn "STAGING mode — certs will NOT be trusted by browsers"
else
  SERVER="letsencrypt"
fi

# Reload the host nginx after each install so new certs take effect. Override
# RELOAD_CMD if nginx runs elsewhere (e.g. a container or a non-systemd host).
RELOAD="${RELOAD_CMD:-sudo systemctl reload nginx} || true"

# Full name list: apex + each subdomain.
domains=("$BASE_DOMAIN")
for s in "${SUBDOMAINS[@]}"; do domains+=("${s}.${BASE_DOMAIN}"); done

log "CA=$SERVER  names: ${domains[*]}"

# Register the ACME account once (idempotent).
"$ACME" --register-account -m "$LE_EMAIL" --server "$SERVER" >/dev/null 2>&1 || true

# ---- issue + install one cert per name --------------------------------------
issued=0
for d in "${domains[@]}"; do
  log "issuing $d (OVH DNS-01)"
  rc=0
  "$ACME" --issue --dns dns_ovh --server "$SERVER" --keylength ec-256 -d "$d" || rc=$?
  # acme.sh: 0 = issued/renewed, 2 = skipped (cert still valid, not due). Both ok.
  case "$rc" in
    0|2) ;;
    *) die "acme.sh failed for $d (rc=$rc). If this is the first OVH run, follow
        the consumer-key authorization URL printed above, set OVH_CK in .env, re-run." ;;
  esac

  mkdir -p "$CERT_DIR/$d"
  "$ACME" --install-cert -d "$d" --ecc \
    --key-file       "$CERT_DIR/$d/key.pem" \
    --fullchain-file "$CERT_DIR/$d/cert.pem" \
    --reloadcmd      "$RELOAD"
  echo "  installed -> $CERT_DIR/$d/{cert.pem,key.pem}"
  issued=$((issued+1))
done

log "done — $issued certificate(s) under $CERT_DIR/"
echo "  serve them: point nginx at certs/<name>/ — see nginx/ulicraft.conf.tmpl"
echo "  renewals: acme.sh installs a cron; --reloadcmd reloads nginx automatically."
