#!/usr/bin/env bash
# Issue OpenVPN server cert (vpnserver + CN friendlytv.site by default), ensure dh.pem,
# copy into /etc/openvpn/server/. Run on the VPN host as root.
#
#   sudo bash issue-openvpn-server-cert.sh
#   sudo VPN_EASYRSA_DIR=/var/lib/easy-rsa bash issue-openvpn-server-cert.sh
#   sudo bash issue-openvpn-server-cert.sh --restart
#
# If /etc/openvpn/server/server.conf is missing, a template is installed from server.conf.example
# (disable with --no-init-config). openvpn-server@server requires this file.
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
EASYRSA_HOME="${VPN_EASYRSA_DIR:-/opt/easy-rsa}"
EASYRSA_USER="${EASYRSA_USER:-www-data}"
SERVER_BASENAME="${VPN_SERVER_NAME:-vpnserver}"
SERVER_CN="${VPN_SERVER_CN:-friendlytv.site}"
DEST="${OPENVPN_SERVER_DIR:-/etc/openvpn/server}"
DO_RESTART=0
INIT_CONFIG=1

for arg in "$@"; do
  case "$arg" in
    --restart) DO_RESTART=1 ;;
    --no-init-config) INIT_CONFIG=0 ;;
    -h|--help)
      echo "Usage: sudo bash $0 [--restart] [--no-init-config]"
      echo "Env: VPN_EASYRSA_DIR (default $EASYRSA_HOME), EASYRSA_USER (default $EASYRSA_USER),"
      echo "     VPN_SERVER_NAME (default $SERVER_BASENAME), VPN_SERVER_CN (default $SERVER_CN),"
      echo "     OPENVPN_SERVER_DIR (default $DEST)"
      exit 0
      ;;
  esac
done

run_easyrsa() {
  sudo -u "$EASYRSA_USER" bash -c "cd '$EASYRSA_HOME' && $*"
}

if [[ "$(id -u)" -ne 0 ]]; then
  echo "Run as root: sudo bash $0" >&2
  exit 1
fi

if [[ ! -x "$EASYRSA_HOME/easyrsa" ]]; then
  echo "Easy-RSA not found: $EASYRSA_HOME/easyrsa (set VPN_EASYRSA_DIR)" >&2
  exit 1
fi

if [[ ! -f "$EASYRSA_HOME/pki/ca.crt" ]]; then
  echo "No CA yet: $EASYRSA_HOME/pki/ca.crt — run init-easy-rsa-pki.sh first." >&2
  exit 1
fi

if ! id "$EASYRSA_USER" &>/dev/null; then
  echo "User not found: $EASYRSA_USER (set EASYRSA_USER)" >&2
  exit 1
fi

echo "==> Easy-RSA: $EASYRSA_HOME (user $EASYRSA_USER)"
echo "==> Server cert: basename=$SERVER_BASENAME CN=$SERVER_CN"

CRT_PATH="$EASYRSA_HOME/pki/issued/${SERVER_BASENAME}.crt"
KEY_PATH="$EASYRSA_HOME/pki/private/${SERVER_BASENAME}.key"
DH_PATH="$EASYRSA_HOME/pki/dh.pem"

if [[ -f "$CRT_PATH" ]]; then
  echo "==> Already exists: $CRT_PATH (delete issued/private req files to re-issue)"
else
  echo "==> gen-req $SERVER_BASENAME"
  run_easyrsa "EASYRSA_BATCH=1 EASYRSA_REQ_CN='$SERVER_CN' ./easyrsa gen-req '$SERVER_BASENAME' nopass"
  echo "==> sign-req server $SERVER_BASENAME"
  run_easyrsa "EASYRSA_BATCH=1 ./easyrsa sign-req server '$SERVER_BASENAME'"
fi

if [[ ! -f "$DH_PATH" ]]; then
  echo "==> gen-dh (can take a minute)..."
  run_easyrsa "EASYRSA_BATCH=1 ./easyrsa gen-dh"
else
  echo "==> Using existing $DH_PATH"
fi

mkdir -p "$DEST"
install -m 0644 -o root -g root "$EASYRSA_HOME/pki/ca.crt" "$DEST/ca.crt"
install -m 0644 -o root -g root "$CRT_PATH" "$DEST/${SERVER_BASENAME}.crt"
install -m 0600 -o root -g root "$KEY_PATH" "$DEST/${SERVER_BASENAME}.key"
install -m 0644 -o root -g root "$DH_PATH" "$DEST/dh.pem"

if ! openssl dhparam -in "$DEST/dh.pem" -check -noout 2>/dev/null; then
  echo "WARNING: openssl dhparam -check failed on $DEST/dh.pem — regenerate:" >&2
  echo "  sudo rm -f '$DH_PATH' && sudo -u $EASYRSA_USER bash -c 'cd $EASYRSA_HOME && EASYRSA_BATCH=1 ./easyrsa gen-dh'" >&2
  echo "  Then re-run this script." >&2
else
  dh_bytes="$(wc -c <"$DEST/dh.pem" | tr -d ' ')"
  if [[ "${dh_bytes:-0}" -lt 1000 ]]; then
    echo "Note: $DEST/dh.pem is ${dh_bytes} bytes; openssl -check passed — OK to use."
  fi
fi

echo "==> Installed:"
ls -la "$DEST/ca.crt" "$DEST/${SERVER_BASENAME}.crt" "$DEST/${SERVER_BASENAME}.key" "$DEST/dh.pem"

CONF_PATH="$DEST/server.conf"
EXAMPLE="$SCRIPT_DIR/server.conf.example"
if [[ ! -f "$CONF_PATH" ]]; then
  if [[ "$INIT_CONFIG" -eq 1 && -f "$EXAMPLE" ]]; then
    sed "s/@SERVER_BASENAME@/${SERVER_BASENAME}/g" "$EXAMPLE" >"$CONF_PATH.tmp"
    install -m 0644 -o root -g root "$CONF_PATH.tmp" "$CONF_PATH"
    rm -f "$CONF_PATH.tmp"
    mkdir -p /var/log/openvpn
    echo "==> Created $CONF_PATH from server.conf.example (review push routes / NAT / firewall)"
  else
    echo "WARNING: $CONF_PATH is missing — openvpn-server@server will not start until it exists." >&2
    echo "  Copy from $EXAMPLE or run without --no-init-config" >&2
  fi
else
  echo "==> Using existing $CONF_PATH (not modified)"
fi

echo ""
echo "Config paths (must match $CONF_PATH):"
echo "  ca $DEST/ca.crt"
echo "  cert $DEST/${SERVER_BASENAME}.crt"
echo "  key $DEST/${SERVER_BASENAME}.key"
echo "  dh $DEST/dh.pem"

if [[ "$DO_RESTART" -eq 1 ]]; then
  restarted=0
  unit=""
  if systemctl cat openvpn-server@server.service &>/dev/null; then
    unit="openvpn-server@server"
  elif systemctl cat openvpn@server.service &>/dev/null; then
    unit="openvpn@server"
  fi
  if [[ -z "$unit" ]]; then
    echo "Could not find openvpn-server@server or openvpn@server; restart OpenVPN manually." >&2
    systemctl list-units 'openvpn*' --all 2>/dev/null || true
    exit 1
  fi
  if [[ ! -f "$CONF_PATH" ]]; then
    echo "ERROR: $CONF_PATH missing — cannot restart OpenVPN." >&2
    exit 1
  fi
  if systemctl restart "$unit"; then
    echo "==> restarted $unit"
    restarted=1
  else
    echo "==> systemctl restart $unit failed — recent logs:" >&2
    journalctl -u "$unit" -n 40 --no-pager >&2 || true
    exit 1
  fi
  ss -ulnp | grep 1194 || echo "Warning: nothing listening on UDP 1194 yet."
else
  echo ""
  echo "To restart OpenVPN after editing server.conf: sudo bash $0 --restart"
fi
