#!/usr/bin/env bash
# DPF cloud-init installer — AWS single-VM
#
# This file is a Terraform templatefile (infra/terraform/single-vm/aws/main.tf).
# Variables in ${ } are Terraform inputs resolved before cloud-init runs.
# Bash variable references using curly braces are written as $${ } in the
# template source to avoid collision with Terraform's interpolation syntax.
#
# Rendered script runs as root under cloud-init on Ubuntu 24.04 LTS.
# All output is tee'd to /var/log/dpf-install.log for post-launch inspection.
#
# Track progress after terraform apply:
#   aws ssm start-session --target <instance_id> \
#     --document-name AWS-StartInteractiveCommand \
#     --parameters command='tail -f /var/log/dpf-install.log'

set -euo pipefail

exec > >(tee -a /var/log/dpf-install.log) 2>&1

DPF_DIR="/opt/dpf"

echo ""
echo "============================================================"
echo "  DPF cloud-init starting at $(date -u)"
echo "  Repo:   ${dpf_repo_url}"
echo "  Branch: ${dpf_branch}"
echo "============================================================"

# ── 1. System packages ────────────────────────────────────────────────────────
echo ""
echo "-> [1/7] Installing system packages"

export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq \
  curl git ca-certificates gnupg lsb-release apt-transport-https \
  build-essential openssl

echo "  [OK] System packages installed"

# ── 2. Docker Engine (official Docker apt repository) ────────────────────────
echo ""
echo "-> [2/7] Installing Docker Engine"

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
   https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) stable" \
  | tee /etc/apt/sources.list.d/docker.list > /dev/null

apt-get update -qq
apt-get install -y -qq \
  docker-ce docker-ce-cli containerd.io docker-compose-plugin

systemctl enable --now docker

# Verify Docker daemon is reachable before proceeding.
docker info > /dev/null
echo "  [OK] Docker Engine $(docker --version)"

# ── 3. Node.js 24 (NodeSource) ───────────────────────────────────────────────
echo ""
echo "-> [3/7] Installing Node.js 24"

curl -fsSL https://deb.nodesource.com/setup_24.x | bash -
apt-get install -y -qq nodejs

NODE_VER=$(node -v)
echo "  [OK] Node.js $NODE_VER"

# ── 4. pnpm ───────────────────────────────────────────────────────────────────
echo ""
echo "-> [4/7] Installing pnpm"

npm install -g pnpm@10.33.2
PNPM_VER=$(pnpm -v)
echo "  [OK] pnpm $PNPM_VER"

# ── 5. Clone DPF repository ───────────────────────────────────────────────────
echo ""
echo "-> [5/7] Cloning DPF repository"

if [ -d "$DPF_DIR/.git" ]; then
  echo "  Existing clone found — updating to origin/${dpf_branch}"
  git -C "$DPF_DIR" remote set-url origin "${dpf_repo_url}"
  git -C "$DPF_DIR" fetch origin "${dpf_branch}"
  git -C "$DPF_DIR" checkout "${dpf_branch}"
  git -C "$DPF_DIR" reset --hard "origin/${dpf_branch}"
else
  git clone --branch "${dpf_branch}" --depth 1 "${dpf_repo_url}" "$DPF_DIR"
fi

echo "  [OK] Repository at $DPF_DIR ($(git -C "$DPF_DIR" rev-parse --short HEAD))"

# ── 6. Write .env before the installer runs ───────────────────────────────────
# install-dpf.sh skips .env generation when the file already exists (step 9
# of the installer: `if [ ! -f .env ]`). We pre-write it here so Terraform-
# supplied secrets are used instead of installer-generated ones.
#
# The admin password is base64-encoded by Terraform (main.tf) and decoded
# here so any password value is safe regardless of shell metacharacters.
echo ""
echo "-> [6/7] Writing .env with Terraform-supplied configuration"

AUTH_SECRET=$(openssl rand -base64 32)
ENC_KEY=$(openssl rand -hex 32)

# Decode the base64-encoded admin password (encoded in main.tf to handle
# any special characters safely in this bash script).
ADMIN_PASS=$(printf '%s' '${dpf_admin_password_b64}' | base64 --decode)

cat > "$DPF_DIR/.env" << ENVEOF
# Generated by DPF cloud-init (infra/terraform/single-vm/aws)
# To reconfigure: edit this file then run docker compose up -d

# PostgreSQL (internal bridge network — not exposed to the internet)
POSTGRES_USER=dpf
POSTGRES_PASSWORD=dpf_dev
DATABASE_URL=postgresql://dpf:dpf_dev@postgres:5432/dpf

# Neo4j
NEO4J_AUTH=neo4j/dpf_dev_password

# Auth.js secret
AUTH_SECRET=$AUTH_SECRET

# Credential encryption key (64 hex chars = 32 bytes)
CREDENTIAL_ENCRYPTION_KEY=$ENC_KEY

# Host-side install directory (used by the promoter container for Build Studio)
DPF_HOST_INSTALL_PATH=$DPF_DIR

# Backups host path — lives OUTSIDE the install root so a future repo wipe
# cannot destroy operator backup history. See
# docs/superpowers/specs/2026-05-17-postgres-daily-backup-design.md §5.3.
DPF_BACKUPS_HOST_PATH=$DPF_DIR-backups

# Grafana monitoring credentials
GF_ADMIN_USER=admin
GF_ADMIN_PASSWORD=dpf_monitor

# LLM provider — external (cloud VMs do not run Docker Model Runner)
DPF_LLM_PROVIDER=external
LLM_BASE_URL=${llm_base_url}
LLM_MODEL=${llm_model}
EMBEDDING_MODEL=${embedding_model}
BROWSER_USE_MODEL=
DPF_MODEL_PULL_MODE=auto

# Release image distribution (used by docker-compose.release.yml)
GHCR_OWNER=opendigitalproductfactory
DPF_IMAGE_TAG=latest

# MCP transport
MCP_INSECURE_INTERNAL_HOSTS=

# Edge Node (populated post-install by install-dpf.sh if --no-edge not set)
DPF_AUTHORITY_URL=
DPF_BOOTSTRAP_TOKEN=
DPF_EDGE_NODE_NAME=
DPF_INSTALL_MODE=container-vm
ENVEOF

# Write ADMIN_PASSWORD using printf to safely handle any character value.
printf 'ADMIN_PASSWORD=%s\n' "$ADMIN_PASS" >> "$DPF_DIR/.env"

# Hive contribution token (deprecated but kept to avoid install warning).
printf 'HIVE_CONTRIBUTION_TOKEN=\n' >> "$DPF_DIR/.env"

echo "  [OK] .env written"

# ── 7. Run the DPF installer ──────────────────────────────────────────────────
echo ""
echo "-> [7/7] Running DPF installer (this takes 5-10 minutes)"
echo "   --headless  : no interactive prompts"
echo "   --release   : use pre-built GHCR images (no local build)"
echo "   --no-autostart : skip LaunchAgent/systemd-user (Docker restart policies handle reboot)"
echo ""

cd "$DPF_DIR"

# DPF_HEADLESS exported so sourced library functions see it without flag parsing.
export DPF_HEADLESS=1

bash install-dpf.sh --headless --release --no-autostart

# ── Done ──────────────────────────────────────────────────────────────────────
PUBLIC_IP=$(curl -s --max-time 5 http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null || echo "<instance-public-ip>")

echo ""
echo "============================================================"
echo "  DPF cloud-init complete at $(date -u)"
echo ""
echo "  Portal:    http://$PUBLIC_IP:3000"
echo "  Admin:     admin@dpf.local"
echo "  Password:  see ADMIN_PASSWORD in $DPF_DIR/.env"
echo ""
if [ -z "${llm_base_url}" ]; then
echo "  IMPORTANT: LLM_BASE_URL is not configured."
echo "  AI features will not work until you set LLM_BASE_URL, LLM_MODEL,"
echo "  and EMBEDDING_MODEL in $DPF_DIR/.env, then run:"
echo "    cd $DPF_DIR && docker compose up -d"
fi
echo ""
echo "  Log:       /var/log/dpf-install.log"
echo "  Diagnose:  cd $DPF_DIR && bash install-dpf.sh doctor"
echo "============================================================"
