#!/usr/bin/env bash
#
# paas-init — first-boot wizard for a server spawned from the golden template.
#
#   sudo paas-init                # interactive: asks everything, then runs bootstrap.sh
#   sudo paas-init --panel-domain deploy2.example.com --flavour laravel \
#                  --password-file /root/pw.txt --yes      # non-interactive
#
# Asks for: panel domain (management UI), admin password, flavour (Node.js as
# in production, or Laravel = + PHP-FPM/composer/MariaDB), system-domain base,
# ACME e-mail — then pulls the repo (optional) and calls bootstrap.sh with the
# matching environment. Safe to re-run (bootstrap is idempotent; re-running
# with the Laravel flavour upgrades a Node server in place).

set -euo pipefail

REPO_DIR="${PAAS_REPO_DIR:-}"
PANEL_DOMAIN=""; FLAVOUR=""; PASSWORD=""; PASSWORD_FILE=""
SYSTEM_DOMAIN_BASE_IN=""; ACME_EMAIL_IN=""; PHP_VERSIONS_IN=""; DO_PULL=""; YES=0
a=""; f=""; go=""   # answers filled by ask()

usage() {
    cat <<'EOF'
paas-init — set up this server (run as root)

  --panel-domain <fqdn>     management UI domain (DNS must point at this server)
  --flavour node|laravel    node = Caddy+Varnish+PM2 (production); laravel = + PHP-FPM, composer, MariaDB
  --password-file <file>    admin password for the panel (first line); asked interactively otherwise
  --system-domain-base <d>  base for auto-generated app domains (default: younex.de)
  --acme-email <mail>       Let's Encrypt contact (default: info@logyou.de)
  --php-versions "8.3 8.4"  laravel only (default: 8.3 8.4)
  --pull | --no-pull        git pull the repo checkout before bootstrapping (default: ask / pull)
  --repo <dir>              repo checkout to use (default: auto-detect)
  --yes                     no confirmation prompt
EOF
    exit "${1:-0}"
}

while [[ $# -gt 0 ]]; do
    case "$1" in
        --panel-domain)       PANEL_DOMAIN="$2"; shift 2 ;;
        --flavour|--flavor)   FLAVOUR="$2"; shift 2 ;;
        --password-file)      PASSWORD_FILE="$2"; shift 2 ;;
        --system-domain-base) SYSTEM_DOMAIN_BASE_IN="$2"; shift 2 ;;
        --acme-email)         ACME_EMAIL_IN="$2"; shift 2 ;;
        --php-versions)       PHP_VERSIONS_IN="$2"; shift 2 ;;
        --pull)               DO_PULL=1; shift ;;
        --no-pull)            DO_PULL=0; shift ;;
        --repo)               REPO_DIR="$2"; shift 2 ;;
        --yes|-y)             YES=1; shift ;;
        -h|--help)            usage 0 ;;
        *) echo "unknown option: $1" >&2; usage 1 ;;
    esac
done

[[ "$(id -u)" -eq 0 ]] || { echo "run as root: sudo paas-init" >&2; exit 1; }

# ---- locate the repo checkout ----
if [[ -z "$REPO_DIR" ]]; then
    for d in "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." 2>/dev/null && pwd)" /home/younes/dotnews-paas /home/*/dotnews-paas /root/dotnews-paas /opt/dotnews-paas; do
        [[ -f "$d/bootstrap.sh" && -f "$d/bin/paas" ]] && { REPO_DIR="$d"; break; }
    done
fi
[[ -n "$REPO_DIR" && -f "$REPO_DIR/bootstrap.sh" ]] || { echo "cannot find the dotnews-paas checkout (use --repo <dir>)" >&2; exit 1; }
REPO_OWNER="$(stat -c %U "$REPO_DIR")"

bold() { printf '\033[1m%s\033[0m' "$*"; }
hr()   { printf '%s\n' "──────────────────────────────────────────────────────────────"; }
ask()  { # $1 var, $2 prompt, $3 default
    local v
    if [[ -n "$3" ]]; then read -rp "$2 [$3]: " v; else read -rp "$2: " v; fi
    printf -v "$1" '%s' "${v:-$3}"
}
valid_domain() { [[ "$1" =~ ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$ ]]; }

# current state (re-runs)
CUR_FLAVOUR=node
grep -qs '^RUNTIMES=.*laravel' /srv/paas/paas.conf 2>/dev/null && CUR_FLAVOUR=laravel
CUR_PANEL=""
[[ -f /srv/paas/panel/.env ]] && CUR_PANEL="$(sed -n 's#^PANEL_BASE_URL=https\?://##p' /srv/paas/panel/.env | head -1)"
CUR_BASE="$(sed -n 's/^SYSTEM_DOMAIN_BASE=//p' /srv/paas/paas.conf 2>/dev/null | head -1)"

echo
hr; echo " $(bold 'dotnews-paas — server setup wizard')   host: $(hostname)  ip: $(hostname -I 2>/dev/null | awk '{print $1}')"; hr
if [[ -n "$CUR_PANEL" ]]; then
    echo " This server is already set up (panel: $CUR_PANEL, flavour: $CUR_FLAVOUR)."
    echo " Re-running is safe: bootstrap is idempotent and can add the Laravel flavour."
    echo
fi
echo " Repo checkout: $REPO_DIR ($(git -C "$REPO_DIR" log -1 --format='%h %s' 2>/dev/null || echo 'not a git checkout'))"
echo

# ---- 1. update code ----
if [[ -z "$DO_PULL" ]]; then
    if [[ "$YES" -eq 1 ]]; then DO_PULL=1; else
        ask a "Pull the latest platform code first? (y/n)" y
        [[ "$a" =~ ^[Yy] ]] && DO_PULL=1 || DO_PULL=0
    fi
fi
if [[ "$DO_PULL" -eq 1 && -d "$REPO_DIR/.git" ]]; then
    echo " pulling…"
    if sudo -u "$REPO_OWNER" -H git -C "$REPO_DIR" pull --ff-only -q 2>&1 | sed 's/^/   /'; then
        echo " code now at $(git -C "$REPO_DIR" log -1 --format='%h %s')"
    else
        echo " WARNING: git pull failed (no network / no access?) — continuing with the checked-out code" >&2
    fi
    # the wizard itself may have changed — re-exec once from the fresh checkout
    if [[ -z "${PAAS_INIT_REEXEC:-}" && -f "$REPO_DIR/bin/paas-init" ]] && ! cmp -s "$REPO_DIR/bin/paas-init" "${BASH_SOURCE[0]}"; then
        install -m 755 "$REPO_DIR/bin/paas-init" /usr/local/bin/paas-init
        export PAAS_INIT_REEXEC=1
        args=(--no-pull --repo "$REPO_DIR")
        [[ -n "$PANEL_DOMAIN" ]] && args+=(--panel-domain "$PANEL_DOMAIN")
        [[ -n "$FLAVOUR" ]] && args+=(--flavour "$FLAVOUR")
        [[ -n "$PASSWORD_FILE" ]] && args+=(--password-file "$PASSWORD_FILE")
        [[ -n "$SYSTEM_DOMAIN_BASE_IN" ]] && args+=(--system-domain-base "$SYSTEM_DOMAIN_BASE_IN")
        [[ -n "$ACME_EMAIL_IN" ]] && args+=(--acme-email "$ACME_EMAIL_IN")
        [[ -n "$PHP_VERSIONS_IN" ]] && args+=(--php-versions "$PHP_VERSIONS_IN")
        [[ "$YES" -eq 1 ]] && args+=(--yes)
        exec "$REPO_DIR/bin/paas-init" "${args[@]}"
    fi
fi
echo

# ---- 2. questions ----
while [[ -z "$PANEL_DOMAIN" ]] || ! valid_domain "$PANEL_DOMAIN"; do
    [[ -n "$PANEL_DOMAIN" ]] && echo "   invalid domain: $PANEL_DOMAIN"
    [[ "$YES" -eq 1 && -z "$PANEL_DOMAIN" ]] && { echo "--panel-domain is required" >&2; exit 1; }
    echo " 1) $(bold 'Panel domain') — the management UI (login) for THIS server."
    echo "    Each server needs its own (production uses deploy.younex.de). Point its DNS"
    echo "    A-record at this server's WAN alias; Caddy fetches the certificate itself."
    ask PANEL_DOMAIN "    panel domain" "$CUR_PANEL"
    PANEL_DOMAIN="${PANEL_DOMAIN,,}"
done

if [[ -z "$FLAVOUR" ]]; then
    echo
    echo " 2) $(bold 'Flavour') — what this server can run:"
    echo "    [1] Node.js   — Caddy + Varnish + PM2, exactly like production today"
    echo "    [2] Laravel   — the above + PHP-FPM 8.3/8.4, composer, MariaDB ('paas db');"
    echo "                    Node apps still work; Laravel/Database options appear in the panel"
    def=1; [[ "$CUR_FLAVOUR" == "laravel" ]] && def=2
    ask f "    choose" "$def"
    case "$f" in 2|laravel|l) FLAVOUR=laravel ;; *) FLAVOUR=node ;; esac
fi
[[ "$FLAVOUR" =~ ^(node|laravel)$ ]] || { echo "--flavour must be node or laravel" >&2; exit 1; }

if [[ -z "$PASSWORD" && -n "$PASSWORD_FILE" ]]; then
    PASSWORD="$(head -n1 "$PASSWORD_FILE")"
fi
if [[ -z "$PASSWORD" && ! -f /srv/paas/panel/.env ]]; then
    echo
    echo " 3) $(bold 'Admin password') for the panel login (user: admin)"
    while :; do
        read -rsp "    password: " p1; echo
        read -rsp "    repeat:   " p2; echo
        [[ "$p1" == "$p2" ]] || { echo "    passwords differ"; continue; }
        [[ ${#p1} -ge 8 ]] || { echo "    at least 8 characters"; continue; }
        PASSWORD="$p1"; break
    done
elif [[ -z "$PASSWORD" ]]; then
    echo
    echo " 3) Admin password: keeping the existing one (panel already configured)"
fi

echo
echo " 4) $(bold 'System domain base') — every app also gets <app>-<rand>.<base> (wildcard DNS → this server)"
if [[ -z "$SYSTEM_DOMAIN_BASE_IN" ]]; then
    if [[ "$YES" -eq 1 ]]; then SYSTEM_DOMAIN_BASE_IN="${CUR_BASE:-younex.de}"; else ask SYSTEM_DOMAIN_BASE_IN "    base" "${CUR_BASE:-younex.de}"; fi
fi
valid_domain "$SYSTEM_DOMAIN_BASE_IN" || { echo "invalid base domain" >&2; exit 1; }

echo
echo " 5) $(bold "ACME e-mail") — Let's Encrypt contact for certificates"
if [[ -z "$ACME_EMAIL_IN" ]]; then
    if [[ "$YES" -eq 1 ]]; then ACME_EMAIL_IN="info@logyou.de"; else ask ACME_EMAIL_IN "    e-mail" "info@logyou.de"; fi
fi

if [[ "$FLAVOUR" == "laravel" && -z "$PHP_VERSIONS_IN" ]]; then
    echo
    echo " 6) $(bold 'PHP versions') to install (selectable per app)"
    if [[ "$YES" -eq 1 ]]; then PHP_VERSIONS_IN="8.3 8.4"; else ask PHP_VERSIONS_IN "    versions" "8.3 8.4"; fi
fi

# ---- 3. summary + confirm ----
echo
hr; echo " $(bold 'Summary')"; hr
printf '  %-22s %s\n' "panel domain:" "https://$PANEL_DOMAIN"
printf '  %-22s %s\n' "flavour:" "$FLAVOUR$([[ "$FLAVOUR" == laravel ]] && echo " (PHP $PHP_VERSIONS_IN, MariaDB)")"
printf '  %-22s %s\n' "admin password:" "$([[ -n "$PASSWORD" ]] && echo '(set)' || echo '(unchanged)')"
printf '  %-22s %s\n' "system domain base:" "$SYSTEM_DOMAIN_BASE_IN"
printf '  %-22s %s\n' "ACME e-mail:" "$ACME_EMAIL_IN"
printf '  %-22s %s\n' "code:" "$(git -C "$REPO_DIR" log -1 --format='%h %s' 2>/dev/null || echo "$REPO_DIR")"
hr
if [[ "$YES" -ne 1 ]]; then
    ask go "Run the setup now? (y/n)" y
    [[ "$go" =~ ^[Yy] ]] || { echo "aborted — nothing changed"; exit 1; }
fi

# ---- 4. run bootstrap ----
echo
ENV=(PANEL_DOMAIN="$PANEL_DOMAIN" SYSTEM_DOMAIN_BASE="$SYSTEM_DOMAIN_BASE_IN" ACME_EMAIL="$ACME_EMAIL_IN")
[[ -n "$PASSWORD" ]] && ENV+=(PANEL_ADMIN_PASSWORD="$PASSWORD")
if [[ "$FLAVOUR" == "laravel" ]]; then ENV+=(WITH_LARAVEL=1 PHP_VERSIONS="$PHP_VERSIONS_IN"); fi
LOG=/var/log/paas-init.log
echo " running bootstrap.sh (log: $LOG) — a few minutes on first run…"
if ! ( cd "$REPO_DIR" && env "${ENV[@]}" ./bootstrap.sh ) 2>&1 | tee -a "$LOG"; then
    echo
    echo " bootstrap FAILED — see $LOG. Fix the cause and re-run: sudo paas-init" >&2
    exit 1
fi
# an existing SYSTEM_DOMAIN_BASE is not rewritten by bootstrap — apply the answer
if [[ -f /srv/paas/paas.conf ]]; then
    if grep -q '^SYSTEM_DOMAIN_BASE=' /srv/paas/paas.conf; then
        sed -i "s|^SYSTEM_DOMAIN_BASE=.*|SYSTEM_DOMAIN_BASE=$SYSTEM_DOMAIN_BASE_IN|" /srv/paas/paas.conf
    else
        echo "SYSTEM_DOMAIN_BASE=$SYSTEM_DOMAIN_BASE_IN" >>/srv/paas/paas.conf
    fi
fi
grep -qs 'paas-init' /etc/motd && : >/etc/motd     # drop the "not set up yet" banner
install -m 755 "$REPO_DIR/bin/paas-init" /usr/local/bin/paas-init 2>/dev/null || true

# ---- 5. what's left ----
CMK_TOKEN="$(sed -n 's/^CMK_AGENT_TOKEN=//p' /srv/paas/panel/.env 2>/dev/null | head -1)"
WAN_HINT="$(hostname -I 2>/dev/null | awk '{print $1}')"
echo
hr; echo " $(bold 'Setup complete')"; hr
cat <<EOF
  panel:        https://$PANEL_DOMAIN   (login: admin)
  flavour:      $FLAVOUR$(grep -qs '^RUNTIMES=.*laravel' /srv/paas/paas.conf && echo " — Laravel + Database enabled in the panel")
  deploy key:   $(cat /home/deploy/.ssh/id_ed25519.pub 2>/dev/null || echo '(missing?)')

  Still to do outside this VM:
   1. OPNsense: NAT 80/tcp, 443/tcp, 443/udp from a free WAN alias -> $WAN_HINT
   2. DNS: $PANEL_DOMAIN (and later each app domain) -> that WAN alias;
      *.$SYSTEM_DOMAIN_BASE_IN wildcard -> this server if it should serve system domains
   3. Checkmk: host with datasource https://$PANEL_DOMAIN/cmk-agent${CMK_TOKEN:+, token: $CMK_TOKEN}
   4. Git hosts: add the deploy key above for private repositories

  Then: open the panel -> New project$([[ "$FLAVOUR" == laravel ]] && echo ' (Runtime: Node.js or Laravel)')
  Re-run 'sudo paas-init' any time to change the panel domain or add the Laravel flavour.
EOF
