#!/usr/bin/env bash
# ================================================================
# LiberMap — Script de Atualização Remota
# Hospedado em: saas.libernet.com.br/instalador/libermap/update.sh
# Chamado pelo update.sh local do ISP
# ================================================================
set -euo pipefail

NEW_VERSION="${1:-}"
[[ -z "$NEW_VERSION" ]] && echo "Uso: bash update.sh <versão>" && exit 1

BASE_URL="https://saas.libernet.com.br/instalador/libermap"
INSTALL_DIR="/opt/libermap"
APP_USER="libermap"
PG_USER="libermap"

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
ok(){   echo -e "${GREEN}[ OK ]${NC} $*"; }
info(){ echo -e "${CYAN}[INFO]${NC} $*"; }
warn(){ echo -e "${YELLOW}[WARN]${NC} $*"; }
err(){  echo -e "${RED}[ERRO]${NC} $*"; exit 1; }
step(){ echo -e "\n${BOLD}${CYAN}══ $* ══${NC}"; }

CURRENT=$(cat "$INSTALL_DIR/.version" 2>/dev/null || echo "0.0.0")
PG_DB=$(grep "^PGDATABASE=" "$INSTALL_DIR/.env" | cut -d= -f2)
PGPASSWORD=$(grep "^PGPASSWORD=" "$INSTALL_DIR/.env" | cut -d= -f2)

echo ""
echo -e "${BOLD}${CYAN}  LiberMap — Atualizando v${CURRENT} → v${NEW_VERSION}${NC}"
echo ""

# ── 1. Backup antes de tudo ───────────────────────────────────
step "Backup de segurança"
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
PGPASSWORD="$PGPASSWORD" pg_dump -U "$PG_USER" "$PG_DB" | \
  gzip > "$INSTALL_DIR/backups/pre-update-${BACKUP_DATE}.sql.gz" 2>/dev/null
ok "Banco de dados salvo: pre-update-${BACKUP_DATE}.sql.gz"

cp "$INSTALL_DIR/src/server.js" \
   "$INSTALL_DIR/backups/server-${CURRENT}-${BACKUP_DATE}.js" 2>/dev/null || true
ok "server.js anterior preservado"

# ── 2. Baixa novos arquivos ───────────────────────────────────
step "Baixando v${NEW_VERSION}"
TMP=$(mktemp -d)
trap "rm -rf $TMP" EXIT

# Baixa o install.sh novo que contém todos os arquivos embutidos
# e extrai apenas os arquivos de código (pula configuração/banco/serviços)
curl -fsSL "$BASE_URL/install.sh" -o "$TMP/install.sh" || \
  err "Falha ao baixar install.sh de $BASE_URL"
ok "install.sh v${NEW_VERSION} baixado"

# Extrai apenas os heredocs de código-fonte para um diretório temporário
# (usa Python para fazer o parse seguro do install.sh)
python3 << PYEOF
import re, os, subprocess

install_sh = open('$TMP/install.sh').read()

# Encontra todos os blocos: cat > "\$INSTALL_DIR/caminho" << 'HEREDOC_EOF'
pattern = r"cat > \"\\\$INSTALL_DIR/([^\"]+)\" << 'HEREDOC_EOF'\n(.*?)\nHEREDOC_EOF"
matches = re.findall(pattern, install_sh, re.DOTALL)

extracted = 0
for filepath, content in matches:
    # Ignora arquivos de configuração gerados dinamicamente
    if filepath in ['.env', '.version', '.update_url']:
        continue
    dest = os.path.join('$TMP/extracted', filepath)
    os.makedirs(os.path.dirname(dest), exist_ok=True)
    with open(dest, 'w') as f:
        f.write(content + '\n')
    extracted += 1

print(f'  {extracted} arquivos extraídos')
PYEOF

ok "Arquivos de código extraídos"

# ── 3. Para o serviço ─────────────────────────────────────────
step "Parando serviço"
systemctl stop libermap
info "LiberMap parado (downtime mínimo durante atualização)"

# ── 4. Aplica novos arquivos ──────────────────────────────────
step "Aplicando atualização"
# Copia apenas src/ e sql/ — preserva .env, logs, backups
if [[ -d "$TMP/extracted" ]]; then
  cp -r "$TMP/extracted/." "$INSTALL_DIR/"
  ok "Arquivos de código atualizados"
else
  err "Extração falhou — nenhum arquivo encontrado"
fi

# ── 5. Migrations novas ───────────────────────────────────────
step "Migrações de banco"
# Busca lista de migrations da versão nova
VERSION_JSON=$(curl -fsSL "$BASE_URL/version.json" 2>/dev/null)
MIGRATIONS=$(python3 -c "
import sys, json
d = json.loads('''$VERSION_JSON''')
for m in d.get('migrations', []):
    print(m)
" 2>/dev/null || echo "")

if [[ -n "$MIGRATIONS" ]]; then
  while IFS= read -r migration; do
    [[ -z "$migration" ]] && continue
    MIGRATION_FILE="$INSTALL_DIR/sql/migrations/${migration}"
    if [[ -f "$MIGRATION_FILE" ]]; then
      PGPASSWORD="$PGPASSWORD" psql -U "$PG_USER" -d "$PG_DB" \
        -f "$MIGRATION_FILE" 2>/dev/null \
        && ok "Migration $migration aplicada" \
        || warn "Migration $migration já aplicada ou com aviso"
    else
      warn "Migration $migration não encontrada localmente"
    fi
  done <<< "$MIGRATIONS"
else
  info "Nenhuma migration nova nesta versão"
fi

# ── 6. npm install (novas dependências) ───────────────────────
step "Dependências"
cd "$INSTALL_DIR" && npm install --production --silent
ok "Dependências atualizadas"

# ── 7. Permissões e versão ────────────────────────────────────
chown -R "$APP_USER:$APP_USER" "$INSTALL_DIR"
echo "$NEW_VERSION" > "$INSTALL_DIR/.version"

# ── 8. Reinicia ───────────────────────────────────────────────
step "Reiniciando"
systemctl start libermap
sleep 4

if systemctl is-active --quiet libermap; then
  ok "LiberMap v${NEW_VERSION} rodando!"
else
  warn "Serviço não iniciou — tentando rollback..."
  # Rollback: restaura server.js anterior
  PREV_SERVER=$(ls -t "$INSTALL_DIR/backups/server-${CURRENT}-"*.js 2>/dev/null | head -1)
  if [[ -n "$PREV_SERVER" ]]; then
    cp "$PREV_SERVER" "$INSTALL_DIR/src/server.js"
    systemctl start libermap
    sleep 3
    systemctl is-active --quiet libermap \
      && warn "Rollback para v${CURRENT} bem-sucedido" \
      || err "Rollback também falhou — verifique: journalctl -u libermap -n 50"
  else
    err "Sem backup para rollback — verifique: journalctl -u libermap -n 50"
  fi
  exit 1
fi

sleep 2
curl -sf http://localhost:3000/health >/dev/null 2>&1 && ok "Health check OK" || \
  warn "Health não respondeu ainda — aguarde"

echo ""
echo -e "${BOLD}${GREEN}════════════════════════════════════════════════════${NC}"
echo -e "${BOLD}${GREEN}  LiberMap atualizado: v${CURRENT} → v${NEW_VERSION}${NC}"
echo -e "${BOLD}${GREEN}════════════════════════════════════════════════════${NC}"
echo ""
echo -e "  Logs: ${CYAN}journalctl -u libermap -f${NC}"
echo ""
