#!/usr/bin/env bash
# =============================================================================
# Redeploy del complemento de Outlook SIAC (y sus dependencias de backend).
#
# Qué hace, en orden y con downtime mínimo:
#   1. Verifica que los archivos del add-in y el manifiesto existen.
#   2. Reconstruye el worker `pptxgen` (nueva dependencia: python-docx para .docx).
#   3. Reconstruye el `api` (módulos nuevos: docgen, graph + streaming en chat).
#   4. Recrea ambos contenedores y recarga el contenedor de add-ins (estático).
#   5. Verifica salud del API, del worker y que las URLs públicas respondan 200.
#   6. Informa si Microsoft Graph (SSO) está configurado o en modo degradado.
#
# Las imágenes se construyen ANTES de recrear los contenedores (el build no causa
# downtime). El healthcheck de Traefik solo enruta tráfico al contenedor sano.
#
# Uso:
#   cd /opt/siac-ia/deploy && ./redeploy-outlook.sh
#
# Requisitos: ejecutarse en el servidor, con Docker y permisos sobre el stack.
# =============================================================================
set -euo pipefail

cd "$(dirname "$0")"

COMPOSE="docker compose -f docker-compose.server.yml -p siac-ia"
BASE="https://ia.siac.com.co"
ADDINS_ROOT="/opt/siac-ia/addins"

ok()   { printf '   \033[32m✓\033[0m %s\n' "$1"; }
warn() { printf '   \033[33m!\033[0m %s\n' "$1"; }
die()  { printf '\033[31m✗ %s\033[0m\n' "$1" >&2; exit 1; }

echo "==> 0/6 Comprobando archivos del complemento de Outlook..."
need_files=(
  "$ADDINS_ROOT/outlook/index.html"
  "$ADDINS_ROOT/outlook/assets/index-OL.js"
  "$ADDINS_ROOT/outlook/assets/index-OL.css"
  "$ADDINS_ROOT/outlook/assets/icon-32.png"
  "$ADDINS_ROOT/download/siac-outlook.manifest.xml"
)
for f in "${need_files[@]}"; do
  [ -f "$f" ] || die "Falta el archivo requerido: $f"
done
ok "Archivos del add-in presentes."

# El manifiesto se distribuye SIN <WebApplicationInfo> activo (un App ID de ejemplo provoca
# un error 400 al instalar en Outlook web). Avisamos si el SSO aún no está cableado.
if ! grep -qE '^[[:space:]]*<WebApplicationInfo>' "$ADDINS_ROOT/download/siac-outlook.manifest.xml"; then
  warn "El manifiesto NO incluye <WebApplicationInfo> (SSO desactivado). El add-in instalará y"
  warn "funcionará en modo degradado. Para Microsoft 365 (hilos/búsqueda/calendario), registra"
  warn "la app en Entra ID y descomenta/añade el bloque <WebApplicationInfo> (ver manual de admin)."
fi

echo "==> 1/6 Construyendo worker pptxgen (python-docx para .docx)..."
$COMPOSE build pptxgen
ok "Imagen de pptxgen construida."

echo "==> 2/6 Construyendo api (docgen + graph + streaming)..."
$COMPOSE build api
ok "Imagen de api construida."

echo "==> 3/6 Recreando worker pptxgen..."
$COMPOSE up -d --no-deps pptxgen
ok "pptxgen recreado."

echo "==> 4/6 Recreando api..."
$COMPOSE up -d --no-deps api

echo "==> 5/6 Recreando contenedor de complementos (aplica la ruta /outlook de Traefik)..."
# IMPORTANTE: la regla de Traefik que enruta /outlook al contenedor de complementos vive
# en las labels del servicio `addins` (docker-compose.server.yml). Esas labels solo se
# aplican al RECREAR el contenedor (`up -d`), NO con `restart` ni con `nginx -s reload`.
# Sin esto, /outlook cae en el SPA del panel y el complemento no arranca.
$COMPOSE up -d --no-deps addins
ok "Complementos recreados (ruta /outlook activa)."

echo "==> 6/6 Verificando salud y URLs públicas..."

# API /health
api_ok=0
for i in $(seq 1 30); do
  if curl -fsS -m 5 "$BASE/health" >/dev/null 2>&1; then api_ok=1; ok "API sano ($BASE/health)."; break; fi
  sleep 2
done
[ "$api_ok" = 1 ] || die "El API no respondió /health. Revisa: $COMPOSE logs api"

# Worker pptxgen (interno, vía exec)
if $COMPOSE exec -T pptxgen python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8090/health',timeout=3).status==200 else 1)" 2>/dev/null; then
  ok "Worker pptxgen sano (/health interno)."
else
  warn "No pude verificar /health del worker pptxgen (puede tardar en arrancar). Revisa: $COMPOSE logs pptxgen"
fi

# Taskpane público
code_tp=$(curl -fsS -o /dev/null -w '%{http_code}' -m 8 "$BASE/outlook/index.html" || echo "000")
[ "$code_tp" = "200" ] && ok "Taskpane disponible: $BASE/outlook/index.html" || warn "Taskpane devolvió HTTP $code_tp (esperado 200)."

# JS del add-in
code_js=$(curl -fsS -o /dev/null -w '%{http_code}' -m 8 "$BASE/outlook/assets/index-OL.js" || echo "000")
[ "$code_js" = "200" ] && ok "Bundle JS disponible: /outlook/assets/index-OL.js" || warn "El JS devolvió HTTP $code_js (esperado 200)."

# Manifiesto público
code_mf=$(curl -fsS -o /dev/null -w '%{http_code}' -m 8 "$BASE/download/siac-outlook.manifest.xml" || echo "000")
[ "$code_mf" = "200" ] && ok "Manifiesto disponible: $BASE/download/siac-outlook.manifest.xml" || warn "El manifiesto devolvió HTTP $code_mf (esperado 200)."

# Estado de Microsoft Graph (SSO) — informativo, requiere un login; aquí solo leemos config.
if $COMPOSE exec -T api python -c "from app.core.config import settings; import sys; sys.exit(0 if settings.graph_enabled else 3)" 2>/dev/null; then
  ok "Microsoft Graph (SSO) CONFIGURADO: hilos, búsqueda, calendario y contactos activos."
else
  warn "Microsoft Graph (SSO) en MODO DEGRADADO (sin MS_CLIENT_ID/SECRET): el add-in funciona"
  warn "solo con el correo abierto. Configura Entra ID en .env para habilitar Graph (ver manual admin)."
fi

echo ""
echo "==> Redeploy de Outlook completo."
echo "    Manifiesto para sideload/despliegue: $BASE/download/siac-outlook.manifest.xml"
echo "    Manual de usuario:  $BASE/manuales/outlook.html"
echo "    Manual de admin:    $BASE/manuales/admin.html"
