#!/usr/bin/env bash
# Instala AgentiCo One como servicio de systemd con un usuario sin privilegios
# (probado para Ubuntu 24.04). No borra ni mueve datos: cambia el dueño de la
# carpeta de trabajo y deja el binario y la configuración en solo lectura para
# el servicio. Guía completa: docs/SERVIDOR_LINUX.md.
#
#   sudo ./instalar-servicio.sh --dir /opt/agentico [--workspace RUTA] [--args "-webapp"] [--sin-cloud]
#
#   --dir        carpeta con agentico-one, setup.json y users.json
#   --workspace  carpeta de trabajo (por defecto <dir>/workspace)
#   --args       opciones del binario (por defecto -webapp)
#   --sin-cloud  no instala agentico-host (la sección Cloud de la web)
set -euo pipefail

dir="" workspace="" args="-webapp" cloud=1
user="agentico" home="/var/lib/agentico"
unit="/etc/systemd/system/agentico.service"
template="$(dirname "$(realpath "$0")")/agentico.service"
host_unit="/etc/systemd/system/agentico-host.service"
host_template="$(dirname "$(realpath "$0")")/agentico-host.service"

fail() { echo "Error: $*" >&2; exit 1; }

while [ $# -gt 0 ]; do
	case "$1" in
	--dir) dir="${2:-}"; shift 2 ;;
	--workspace) workspace="${2:-}"; shift 2 ;;
	--args) args="${2:-}"; shift 2 ;;
	--sin-cloud) cloud=0; shift ;;
	-h | --help) sed -n '2,13p' "$0"; exit 0 ;;
	*) fail "opción desconocida: $1 (usa --help)" ;;
	esac
done

[ "$(id -u)" -eq 0 ] || fail "ejecuta el script con sudo."
[ -n "$dir" ] || fail "indica --dir con la carpeta del binario."
[ -f "$template" ] || fail "falta $template junto al script."
[ "$cloud" -eq 0 ] || [ -f "$host_template" ] || fail "falta $host_template junto al script (o usa --sin-cloud)."
dir="$(realpath "$dir")"
bin="$dir/agentico-one"
[ -x "$bin" ] || fail "no existe el ejecutable $bin."
workspace="${workspace:-$dir/workspace}"
case "$workspace" in /*) ;; *) workspace="$dir/$workspace" ;; esac
workspace="$(realpath -m "$workspace")"
for path in "$dir" "$workspace"; do
	case "$path/" in
	/root/*) fail "$path está bajo /root, que el servicio no puede ver. Muévelo, por ejemplo, a /opt/agentico." ;;
	/home/) fail "usa una carpeta propia dentro de /home, no /home." ;;
	*' '*) fail "$path contiene espacios; usa una ruta sin espacios." ;;
	esac
done
# Bajo /home el servicio no ve nada (ProtectHome) salvo lo que se le monta:
# la carpeta del binario y, si está aparte, la de trabajo. Así no hace falta
# abrir los permisos de la carpeta personal que la contiene.
binds=""
case "$dir/" in /home/*) binds="$dir" ;; esac
case "$workspace/" in
/home/*) case "$workspace/" in "$dir"/*) ;; *) binds="$binds $workspace -$workspace-projects" ;; esac ;;
esac
protect_home="yes" bind_line="# AgentiCo One no está bajo /home."
if [ -n "$binds" ]; then
	protect_home="tmpfs" bind_line="BindPaths=${binds# }"
fi
case "$args" in *-workspace*) fail "indica la carpeta de trabajo con --workspace, no dentro de --args." ;; esac

# 1. Usuario de sistema, sin contraseña ni shell.
if ! id "$user" >/dev/null 2>&1; then
	useradd --system --home-dir "$home" --shell /usr/sbin/nologin "$user"
	echo "Usuario $user creado."
fi
install -d -o "$user" -g "$user" -m 0750 "$home"

# 2. Configuración inicial: si faltan setup.json o users.json, el binario deja
# las plantillas junto a sí para completarlas después. No reemplaza nada.
if ! "$bin" -init -workspace "$workspace"; then
	echo "Aviso: este binario no crea las plantillas (-init); se usa la configuración incluida."
fi

# 3. Binario y configuración: siguen siendo de root; el servicio solo los lee.
chown root:"$user" "$dir" "$bin"
chmod 0750 "$dir" "$bin"
for file in setup.json users.json; do
	if [ -f "$dir/$file" ]; then
		chown root:"$user" "$dir/$file"
		chmod 0640 "$dir/$file"
	fi
done

# 4. Datos (workspace, usuarios, proyectos y sesiones): pasan al servicio. La
# unidad, además, los crea y les corrige el dueño cada vez que arranca.
install -d -m 0750 "$workspace" "$workspace-projects"
chown -R "$user:$user" "$workspace" "$workspace-projects"
chmod -R u+rwX,g-w,o-rwx "$workspace" "$workspace-projects"

# 5. Unidad de systemd. Una anterior con el mismo nombre se respalda.
if [ -f "$unit" ]; then
	backup="$unit.respaldo-$(date +%Y%m%d-%H%M%S)"
	cp -p "$unit" "$backup"
	echo "Unidad anterior respaldada en $backup."
fi
sed -e "s|@DIR@|$dir|g" -e "s|@WORKSPACE@|$workspace|g" -e "s|@ARGS@|$args|g" \
	-e "s|@USER@|$user|g" -e "s|@HOME@|$home|g" -e "s|@PROTECT_HOME@|$protect_home|g" \
	-e "s|@BIND_PATHS@|$bind_line|g" "$template" >"$unit"
chmod 0644 "$unit"

# 6. Variables propias del servicio (las lee systemd como root).
install -d -m 0755 /etc/agentico
if [ ! -f /etc/agentico/agentico.env ]; then
	install -m 0600 /dev/null /etc/agentico/agentico.env
fi

# 7. agentico-host: administración del equipo desde la sección Cloud de la web.
if [ "$cloud" -eq 1 ]; then
	if [ -f "$host_unit" ]; then
		cp -p "$host_unit" "$host_unit.respaldo-$(date +%Y%m%d-%H%M%S)"
	fi
	sed -e "s|@DIR@|$dir|g" -e "s|@USER@|$user|g" "$host_template" >"$host_unit"
	chmod 0644 "$host_unit"
fi
systemctl daemon-reload

cat <<EOF

Servicio instalado en $unit.
  Ejecutable: $bin $args
  Workspace:  $workspace (dueño: $user)

Siguientes pasos:
  1. Detén el proceso que hoy corre como root.
  2. sudo systemctl enable --now agentico
     sudo systemctl enable --now agentico-host   # sección Cloud (omítelo si usaste --sin-cloud)
  3. journalctl -u agentico -f        # para ver el arranque
  4. Revisa qué programas ve el agente sin root:
     sudo -u $user env HOME=$home $bin -entorno
  5. Completa $dir/setup.json (dominio, puerto, correo) y $dir/users.json
     (quién entra a la web) con sudo, y reinicia: sudo systemctl restart agentico

Para actualizar, copia solo el binario nuevo sobre $bin y reinicia el servicio.
No reemplaces la carpeta completa ni lances el binario con sudo: los datos están
en $workspace y deben seguir siendo de $user.
EOF
