#!/bin/bash
# Atualiza arquivos com backup, validação de tamanho mínimo, e rollback no restart.
set -euo pipefail

SERVICE_NAME="xcontact"
DO_RESTART="yes"   # mude para "no" se não quiser reiniciar agora

# ---- Mapa LOCAL -> URL ----
declare -A FILES=(
  ["/opt/xcontact/xcontact-server/xc_modules/omni/index.js"]="http://www.xcontactcenter.com.br/dw/mcs/fix-idwhats/index.js"
  ["/opt/xcontact/xcontact-server/xc_modules/omni/api/client/events/handlers.js"]="http://www.xcontactcenter.com.br/dw/mcs/fix-idwhats/handlers.js"
)

# ---- Tamanho mínimo esperado (bytes) para evitar gravação de arquivo vazio/HTML ----
# Observado no diretório público em 11/11/2025: index.js ~117.7 KB; handlers.js ~38.5 KB
declare -A MIN_BYTES=(
  ["/opt/xcontact/xcontact-server/xc_modules/omni/index.js"]=80000
  ["/opt/xcontact/xcontact-server/xc_modules/omni/api/client/events/handlers.js"]=20000
)

# Deps
for b in curl file; do
  command -v "$b" >/dev/null 2>&1 || { echo "Erro: '$b' não está no PATH"; exit 1; }
done
command -v gzip >/dev/null 2>&1 || true

TS="$(date +%Y%m%d_%H%M%S)"
BACKUP_DIR="/opt/xcontact/bkp_${TS}"
UPDATED_LIST=()
mkdir -p "$BACKUP_DIR"

say(){ echo -e "$*"; }

download_checked() {
  local url="$1" out="$2"
  local tmp="$(mktemp)"
  local hdr="$(mktemp)"

  # Tenta baixar com follow redirect + falha em HTTP != 200
  if ! curl -fsSL --retry 3 --connect-timeout 10 --max-time 120 -D "$hdr" -o "$tmp" "$url"; then
    say "   ERRO: download falhou de $url"
    rm -f "$tmp" "$hdr"
    return 1
  fi

  # Verifica se não veio HTML
  if grep -qiE '<(html|head|body|!DOCTYPE)' "$tmp"; then
    say "   ERRO: conteúdo parece HTML (provável página de erro/redirect)"
    rm -f "$tmp" "$hdr"
    return 2
  fi

  # Se veio gzip, tenta descompactar “no ar”
  local mime
  mime="$(file -b --mime-type "$tmp" || true)"
  if [[ "$mime" =~ gzip ]]; then
    if command -v gzip >/dev/null 2>&1; then
      local tmp2="$(mktemp)"
      if ! gzip -dc "$tmp" > "$tmp2"; then
        say "   ERRO: falha ao descomprimir gzip"
        rm -f "$tmp" "$tmp2" "$hdr"
        return 3
      fi
      mv -f "$tmp2" "$tmp"
    else
      say "   ERRO: recebido gzip mas 'gzip' não está instalado"
      rm -f "$tmp" "$hdr"
      return 4
    fi
  fi

  # Tamanho mínimo (se definido para este arquivo)
  local min_bytes="${3:-0}"
  local sz
  sz=$(wc -c < "$tmp")
  if [ "$sz" -lt "$min_bytes" ]; then
    say "   ERRO: arquivo baixado tem $sz bytes (< $min_bytes). Abortando substituição."
    say "        (Dica: verifique Content-Type/Status com: curl -I '$url')"
    rm -f "$tmp" "$hdr"
    return 5
  fi

  mv -f "$tmp" "$out"
  rm -f "$hdr"
  return 0
}

say "Backup em: $BACKUP_DIR"
say "Iniciando atualização…"

for LOCAL in "${!FILES[@]}"; do
  URL="${FILES[$LOCAL]}"
  DEST_DIR="$(dirname "$LOCAL")"
  mkdir -p "$DEST_DIR"

  say ""
  say "=> Atualizando: $LOCAL"
  # Backup se existir
  if [ -f "$LOCAL" ]; then
    mkdir -p "$BACKUP_DIR$DEST_DIR"
    cp -a "$LOCAL" "$BACKUP_DIR$DEST_DIR/"
    say "   Backup: $BACKUP_DIR$DEST_DIR/$(basename "$LOCAL")"
  fi

  TMPDL="$(mktemp)"
  MIN="${MIN_BYTES[$LOCAL]:-0}"

  if download_checked "$URL" "$TMPDL" "$MIN"; then
    # Preserva permissões/dono se já existia
    if [ -f "$LOCAL" ]; then
      perms=$(stat -c "%a" "$LOCAL" 2>/dev/null || stat -f "%Lp" "$LOCAL" 2>/dev/null || echo "0644")
      owner=$(stat -c "%u:%g" "$LOCAL" 2>/dev/null || echo "")
      cp -f "$TMPDL" "$LOCAL"
      [ -n "$owner" ] && chown "$owner" "$LOCAL" || true
      chmod "$perms" "$LOCAL" || true
    else
      install -m 0644 "$TMPDL" "$LOCAL"
    fi
    UPDATED_LIST+=("$LOCAL")
    say "   OK: substituído. (novo tamanho: $(wc -c < "$LOCAL") bytes)"
  else
    rc=$?
    say "   ERRO: falha no download/validação (código $rc). Mantido o original."
  fi
  rm -f "$TMPDL"
done

if [ "${DO_RESTART}" = "yes" ]; then
  say ""
  say "Reiniciando serviço: ${SERVICE_NAME}…"
  if systemctl restart "${SERVICE_NAME}"; then
    say "✔ Serviço reiniciado."
  else
    say "✖ Falha ao reiniciar. ROLLBACK…"
    for LOCAL in "${UPDATED_LIST[@]}"; do
      REL_DIR="$(dirname "$LOCAL")"
      BAK="$BACKUP_DIR$REL_DIR/$(basename "$LOCAL")"
      if [ -f "$BAK" ]; then
        cp -a "$BAK" "$LOCAL"
        say "   Restaurado: $LOCAL"
      else
        rm -f "$LOCAL" || true
        say "   Aviso: sem backup para $LOCAL (era arquivo novo); removido."
      fi
    done
    systemctl restart "${SERVICE_NAME}" || {
      say "✖ Serviço não voltou após rollback. Veja: journalctl -u ${SERVICE_NAME} -xe"
      exit 1
    }
    say "✔ Serviço voltou após rollback."
    exit 1
  fi
fi

say ""
say "Concluído. Backups em: $BACKUP_DIR"
