#!/usr/bin/env bash
# snapshot-etc.sh — retrato do servidor ANTES de uma mudança grande.
#
# Snapshot de VPS de verdade depende da API do provedor, e nem todo provedor tem.
# Isto cobre o estrago realista: o que muda numa operação do SSHepherd mora em
# /etc, na lista de pacotes e nos serviços ligados. Com estes três dá para
# comparar o depois com o antes é voltar a mao.
#
# Não substitui backup de dados. Banco e arquivos da aplicação são backup.sh.
#
# Uso: snapshot-etc.sh --host <ip> --user <deploy> [--port 22] [--key <chave>] [--motivo harden]
#
# Saída: linhas chave=valor, com `snapshot=<caminho no servidor>`.
# Códigos: 0 ok | 2 argumento | 13 conexão

set -uo pipefail

HOST=""; USER_NAME="root"; PORT=22; KEY_PATH=""; MOTIVO="manual"

while [ $# -gt 0 ]; do
  case "$1" in
    --host)   HOST="$2"; shift 2 ;;
    --user)   USER_NAME="$2"; shift 2 ;;
    --port)   PORT="$2"; shift 2 ;;
    --key)    KEY_PATH="$2"; shift 2 ;;
    --motivo) MOTIVO="$2"; shift 2 ;;
    *) echo "argumento desconhecido: $1" >&2; exit 2 ;;
  esac
done

[ -n "$HOST" ] || { echo "ERRO: --host é obrigatório" >&2; exit 2; }

SSH_OPTS=(-o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ForwardAgent=no -o ConnectTimeout=10 -p "$PORT")
[ -n "$KEY_PATH" ] && SSH_OPTS+=(-i "${KEY_PATH/#\~/$HOME}" -o IdentitiesOnly=yes)

STAMP=$(date -u +%Y%m%d%H%M%S)
DEST="/var/backups/sshepherd"

REMOTE=$(cat <<REMOTE_SCRIPT
set -uo pipefail
DEST="${DEST}"
STAMP="${STAMP}"
MOTIVO="${MOTIVO}"
BASE="\${DEST}/\${STAMP}-\${MOTIVO}"

mkdir -p "\$BASE" 2>/dev/null || { echo "erro=sem_permissao_em \${DEST}"; exit 3; }
chmod 700 "\$DEST" 2>/dev/null || true

# /etc inteiro comprimido. Segredo de aplicação não mora aqui, mora em shared/.
tar -czf "\${BASE}/etc.tar.gz" -C / etc 2>/dev/null
echo "etc=\$([ -s "\${BASE}/etc.tar.gz" ] && echo ok || echo falhou)"

# Lista de pacotes: reinstalar exatamente o que existia e o caminho de volta
# quando um apt-get deixou o servidor diferente do que era.
if command -v dpkg >/dev/null 2>&1; then
  dpkg --get-selections > "\${BASE}/pacotes.txt" 2>/dev/null
  echo "pacotes=\$(wc -l < "\${BASE}/pacotes.txt" 2>/dev/null || echo 0)"
fi

# Serviços ligados no boot: o que precisa voltar a subir sozinho.
if command -v systemctl >/dev/null 2>&1; then
  systemctl list-unit-files --state=enabled --no-pager --no-legend \
    > "\${BASE}/servicos.txt" 2>/dev/null
  echo "servicos=\$(wc -l < "\${BASE}/servicos.txt" 2>/dev/null || echo 0)"
fi

# Regras de firewall em texto, para conferir a olho depois.
if command -v ufw >/dev/null 2>&1; then
  ufw status verbose > "\${BASE}/firewall.txt" 2>/dev/null || true
fi

# Só os últimos 10 retratos: disco de VPS é pequeno.
ls -1dt "\${DEST}"/*/ 2>/dev/null | tail -n +11 | xargs -r rm -rf

echo "snapshot=\$BASE"
echo "tamanho=\$(du -sh "\$BASE" 2>/dev/null | cut -f1)"
REMOTE_SCRIPT
)

OUT=$(ssh "${SSH_OPTS[@]}" "${USER_NAME}@${HOST}" "bash -s" <<< "$REMOTE" 2>&1)
CODE=$?

if [ $CODE -eq 255 ]; then
  echo "FALHA DE CONEXAO com ${USER_NAME}@${HOST}:${PORT}" >&2
  exit 13
fi

printf '%s\n' "$OUT"
exit $CODE
