#!/usr/bin/env bash
# =====================================================================
# Despliega el servicio del agente en un server (test o prod). Corre EN el server,
# como root, desde la carpeta del repo (el server no puede clonar kdbf23: se sube
# con rsync, ver docs/despliegue.md).
#
#   bash deploy/desplegar-servidor.sh <base_erp> <dominio> <origen_panel> <env_backend_erp>
#
#   test: bash deploy/desplegar-servidor.sh novasiserp soporte-api.factupy.es \
#           https://facerp.factupy.es /var/www/html/factvoice-erp-api/.env
#
# Idempotente. Qué hace:
#   1. Roles y vistas en la base del ERP (db/aplicar-en-servidor.sh) + verificación.
#   2. Base propia `novasis_soporte` con el rol `soporte_app`.
#   3. .env del servicio. Los secretos salen de archivos de /root (600) y del .env del
#      backend del ERP (JWT_SECRET, HOLDING_EMPRESA_ID): nunca por argumentos.
#      ANTHROPIC_API_KEY: se conserva la del .env actual o se toma de
#      /root/.soporte_anthropic_key. Sin key, el chat queda en modo degradado.
#   4. pnpm install, migraciones de la base propia, build, pm2.
#   5. Vhost de Apache (con flush para el streaming) + certificado, si el DNS ya apunta acá.
#
# Requisito: la migración 20261024200000_soporte_ia_modulo del backend del ERP ya
# aplicada. Sin ella, el servicio responde 403 a todos (no tienen SOP_IA_USAR).
# =====================================================================
set -euo pipefail

BASE_ERP="${1:?Uso: desplegar-servidor.sh <base_erp> <dominio> <origen_panel> <env_backend_erp>}"
DOMINIO="${2:?Falta el dominio (ej. soporte-api.factupy.es)}"
ORIGEN="${3:?Falta el origen del panel (ej. https://facerp.factupy.es)}"
ENV_ERP="${4:?Falta la ruta del .env del backend del ERP}"
PUERTO="${PUERTO:-3020}"
PM2_NOMBRE="${PM2_NOMBRE:-novasis-soporte-ia}"
DIR="$(cd "$(dirname "$0")/.." && pwd)"

[ "$(id -u)" = 0 ] || { echo "Correr como root."; exit 1; }
[ -f "$ENV_ERP" ] || { echo "No existe $ENV_ERP"; exit 1; }

valor_env() { # valor_env <archivo> <CLAVE>: sin comillas envolventes
  grep -E "^$2=" "$1" | tail -1 | cut -d= -f2- | sed -E "s/^['\"](.*)['\"]$/\1/"
}

psql_su() { su postgres -c "cd /tmp && psql -X -q -v ON_ERROR_STOP=1 $*"; }

echo "== 1. roles y vistas en $BASE_ERP"
bash "$DIR/db/aplicar-en-servidor.sh" "$BASE_ERP"

echo "== 2. base propia"
APP_PW_FILE=/root/.soporte_app_pw
if [ ! -s "$APP_PW_FILE" ]; then
  (umask 077 && openssl rand -hex 24 > "$APP_PW_FILE")
  echo "Contraseña nueva de soporte_app en $APP_PW_FILE"
fi
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
(umask 077 && cat > "$TMP/app.sql" <<SQL
\set pw '$(cat "$APP_PW_FILE")'
SELECT 'CREATE ROLE soporte_app LOGIN' WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'soporte_app') \gexec
ALTER ROLE soporte_app LOGIN NOSUPERUSER NOCREATEROLE PASSWORD :'pw';
SELECT 'CREATE DATABASE novasis_soporte OWNER soporte_app' WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'novasis_soporte') \gexec
SQL
)
chown -R postgres "$TMP"
psql_su "-d postgres -f $TMP/app.sql"

# 127.0.0.1 y no localhost: en el server de test localhost resuelve a ::1 y Postgres escucha solo IPv4.
echo "== 3. .env"
JWT="$(valor_env "$ENV_ERP" JWT_SECRET)"
[ -n "$JWT" ] || { echo "JWT_SECRET vacío en $ENV_ERP"; exit 1; }
HOLDING="$(valor_env "$ENV_ERP" HOLDING_EMPRESA_ID || true)"
if [ -z "$HOLDING" ]; then
  HOLDING="$(su postgres -c "cd /tmp && psql -X -At -d $BASE_ERP -c \"SELECT id FROM empresas WHERE type = 'holding' ORDER BY created_at LIMIT 1\"")"
fi
CLAVE_ANTHROPIC=""
[ -f "$DIR/.env" ] && CLAVE_ANTHROPIC="$(valor_env "$DIR/.env" ANTHROPIC_API_KEY || true)"
[ -z "$CLAVE_ANTHROPIC" ] && [ -s /root/.soporte_anthropic_key ] && CLAVE_ANTHROPIC="$(cat /root/.soporte_anthropic_key)"
(umask 077 && cat > "$DIR/.env" <<ENV
# Generado por deploy/desplegar-servidor.sh. No se versiona.
NODE_ENV=production
PORT=$PUERTO
CORS_ORIGINS=$ORIGEN
ERP_DATABASE_URL=postgresql://soporte_ia:$(cat /root/.soporte_ia_pw)@127.0.0.1:5432/$BASE_ERP
ERP_DB_POOL_MAX=5
SOPORTE_DATABASE_URL=postgresql://soporte_app:$(cat "$APP_PW_FILE")@127.0.0.1:5432/novasis_soporte
JWT_SECRET=$JWT
SOPORTE_ALCANCE_SECRETO=$(cat /root/.soporte_alcance_secreto)
HOLDING_EMPRESA_ID=$HOLDING
ANTHROPIC_API_KEY=$CLAVE_ANTHROPIC
ENV
)
[ -n "$CLAVE_ANTHROPIC" ] || echo "AVISO: sin ANTHROPIC_API_KEY el chat queda en modo degradado (poné la key en /root/.soporte_anthropic_key y volvé a correr)."

echo "== 4. build y pm2"
# shellcheck disable=SC1091
source "$HOME/.nvm/nvm.sh" && nvm use 24 >/dev/null
cd "$DIR"
pnpm install --frozen-lockfile
npx prisma migrate deploy
npx prisma generate >/dev/null
pnpm build
if pm2 describe "$PM2_NOMBRE" >/dev/null 2>&1; then
  pm2 restart "$PM2_NOMBRE" --update-env
else
  pm2 start dist/main.js --name "$PM2_NOMBRE"
fi
pm2 save >/dev/null
for _ in $(seq 1 30); do curl -fs "http://127.0.0.1:$PUERTO/api/v1/health" >/dev/null && break; sleep 1; done
curl -fs "http://127.0.0.1:$PUERTO/api/v1/health" && echo || { echo "El servicio no responde en :$PUERTO (pm2 logs $PM2_NOMBRE)"; exit 1; }

echo "== 5. Apache"
VHOST="/etc/apache2/sites-available/$DOMINIO.conf"
if [ ! -f "$VHOST" ]; then
  cat > "$VHOST" <<APACHE
<VirtualHost *:80>
    ServerName $DOMINIO
    ProxyPreserveHost On
    ProxyRequests Off
    # Streaming (SSE): sin flush, Apache entrega la respuesta entera al final.
    ProxyPass / http://127.0.0.1:$PUERTO/ flushpackets=on timeout=180
    ProxyPassReverse / http://127.0.0.1:$PUERTO/
    SetEnv no-gzip 1
    ErrorLog \${APACHE_LOG_DIR}/soporte_ia_error.log
    CustomLog \${APACHE_LOG_DIR}/soporte_ia_access.log combined
</VirtualHost>
APACHE
  a2ensite "$DOMINIO.conf" >/dev/null
  apache2ctl configtest
  systemctl reload apache2
fi
IP_SERVER="$(curl -fs https://api.ipify.org || hostname -I | awk '{print $1}')"
IP_DNS="$(getent hosts "$DOMINIO" | awk '{print $1}' | head -1)"
if [ "$IP_DNS" = "$IP_SERVER" ]; then
  [ -d "/etc/letsencrypt/live/$DOMINIO" ] || certbot --apache -d "$DOMINIO" -n --agree-tos --redirect
  curl -fs "https://$DOMINIO/api/v1/health" && echo " ← https://$DOMINIO OK"
else
  echo "AVISO: $DOMINIO no apunta a este server (DNS: ${IP_DNS:-sin registro}, server: $IP_SERVER)."
  echo "       Creá el registro A y volvé a correr el script para el certificado."
fi
echo "Listo."
