#!/bin/bash
# One-time server setup: create service user, SSH deploy key, age keypair.
# Run as root on a fresh Hetzner server before running bootstrap_supervisor.sh.
#
# Usage:
#   bash infra/setup_server.sh
#
# What it does:
#   1. Creates beanflows_service user (nologin) + adds to docker group
#   2. Creates /opt/materia + /data/materia/landing with correct ownership
#   3. Generates ed25519 SSH deploy key for GitLab read access
#   4. Installs age + sops + rclone to /usr/local/bin (as root)
#   5. Generates age keypair at ~/.config/sops/age/keys.txt (as service user)
#   6. Prints both public keys + numbered next-step instructions

set -euo pipefail

SERVICE_USER="beanflows_service"
APP_DIR="/opt/materia"
DATA_DIR="/data/materia"
SSH_DIR="/home/${SERVICE_USER}/.ssh"
DEPLOY_KEY="${SSH_DIR}/materia_deploy"
SOPS_AGE_DIR="/home/${SERVICE_USER}/.config/sops/age"

[ "$(id -u)" = "0" ] || { echo "ERROR: Run as root: sudo bash infra/setup_server.sh"; exit 1; }

log() { echo "$(date '+%H:%M:%S') ==> $*"; }

# ── Service user ──────────────────────────────────────────────────────────────

log "Creating service user ${SERVICE_USER}..."
if ! id "${SERVICE_USER}" >/dev/null 2>&1; then
    useradd --system --create-home --shell /usr/sbin/nologin "${SERVICE_USER}"
fi
usermod -aG docker "${SERVICE_USER}"
log "User OK."

# ── Directories ───────────────────────────────────────────────────────────────

log "Creating directories..."
mkdir -p "${APP_DIR}" "${DATA_DIR}/landing"
chown "${SERVICE_USER}:${SERVICE_USER}" "${APP_DIR}"
chown -R "${SERVICE_USER}:${SERVICE_USER}" "${DATA_DIR}"
log "Directories OK."

# ── SSH deploy key ────────────────────────────────────────────────────────────

log "Setting up SSH deploy key..."
sudo -u "${SERVICE_USER}" mkdir -p "${SSH_DIR}"
chmod 700 "${SSH_DIR}"

if [ ! -f "${DEPLOY_KEY}" ]; then
    sudo -u "${SERVICE_USER}" ssh-keygen -t ed25519 \
        -f "${DEPLOY_KEY}" -N "" -C "materia-deploy"
fi

sudo -u "${SERVICE_USER}" bash -c "cat > ${SSH_DIR}/config" <<EOF
Host gitlab.com
    IdentityFile ${DEPLOY_KEY}
    IdentitiesOnly yes
EOF
chmod 600 "${SSH_DIR}/config"

sudo -u "${SERVICE_USER}" bash -c \
    "ssh-keyscan -H gitlab.com >> ${SSH_DIR}/known_hosts 2>/dev/null; \
     sort -u ${SSH_DIR}/known_hosts -o ${SSH_DIR}/known_hosts"
chmod 644 "${SSH_DIR}/known_hosts"
log "SSH deploy key OK."

# ── age ───────────────────────────────────────────────────────────────────────

ARCH=$(uname -m)
case "${ARCH}" in
    x86_64)  ARCH_TAG="amd64" ;;
    aarch64) ARCH_TAG="arm64" ;;
    *) echo "Unsupported architecture: ${ARCH}"; exit 1 ;;
esac

if ! command -v age-keygen >/dev/null 2>&1; then
    log "Installing age..."
    AGE_VERSION="v1.3.1"
    curl -fsSL "https://dl.filippo.io/age/${AGE_VERSION}?for=linux/${ARCH_TAG}" -o /tmp/age.tar.gz
    tar -xzf /tmp/age.tar.gz -C /usr/local/bin --strip-components=1 age/age age/age-keygen
    chmod +x /usr/local/bin/age /usr/local/bin/age-keygen
    rm /tmp/age.tar.gz
    log "age installed."
fi

# ── sops ──────────────────────────────────────────────────────────────────────

if ! command -v sops >/dev/null 2>&1; then
    log "Installing sops..."
    SOPS_VERSION="v3.12.1"
    curl -fsSL \
        "https://github.com/getsops/sops/releases/download/${SOPS_VERSION}/sops-${SOPS_VERSION}.linux.${ARCH_TAG}" \
        -o /usr/local/bin/sops
    chmod +x /usr/local/bin/sops
    log "sops installed."
fi

# ── rclone ────────────────────────────────────────────────────────────────────

if ! command -v rclone >/dev/null 2>&1; then
    log "Installing rclone..."
    curl -fsSL https://rclone.org/install.sh | bash
    log "rclone installed."
fi

# ── age keypair (as service user, XDG path auto-discovered by SOPS) ───────────

log "Generating age keypair for ${SERVICE_USER}..."
AGE_KEY_FILE="${SOPS_AGE_DIR}/keys.txt"
if [ ! -f "${AGE_KEY_FILE}" ]; then
    sudo -u "${SERVICE_USER}" mkdir -p "${SOPS_AGE_DIR}"
    sudo -u "${SERVICE_USER}" age-keygen -o "${AGE_KEY_FILE}"
    chmod 600 "${AGE_KEY_FILE}"
    log "Age keypair generated at ${AGE_KEY_FILE}"
else
    log "Age keypair already exists — skipping."
fi

# ── Summary ───────────────────────────────────────────────────────────────────

DEPLOY_PUB=$(cat "${DEPLOY_KEY}.pub")
AGE_PUB=$(grep "public key:" "${AGE_KEY_FILE}" | awk '{print $NF}')

echo ""
echo "=================================================================="
echo ""
echo "  SSH deploy key (add to GitLab → Settings → Deploy Keys):"
echo ""
echo "    ${DEPLOY_PUB}"
echo ""
echo "  Server age public key (add to .sops.yaml):"
echo ""
echo "    ${AGE_PUB}"
echo ""
echo "=================================================================="
echo ""
echo "  Next steps:"
echo ""
echo "  1. Add the SSH deploy key to GitLab:"
echo "       → Repository Settings → Deploy Keys → Add key (read-only)"
echo ""
echo "  2. Add the age public key to .sops.yaml on your workstation:"
echo "       creation_rules:"
echo "         - path_regex: \\.env\\.(dev|prod)\\.sops\$"
echo "           age: >-"
echo "             <dev-key>"
echo "             + ${AGE_PUB}"
echo ""
echo "  3. Re-encrypt prod secrets to include the server key:"
echo "       sops updatekeys .env.prod.sops"
echo "       git add .sops.yaml .env.prod.sops"
echo "       git commit -m 'chore: add server age key'"
echo "       git push"
echo ""
echo "  4. Run bootstrap:"
echo "       bash infra/bootstrap_supervisor.sh"
echo ""
echo "=================================================================="
