#!/usr/bin/env bash
# status.sh — panorama do servidor. SOMENTE LEITURA.
#
# Oito indicadores com limite declarado e classificação. Seguro para rodar em
# produção durante um incidente: não instala nada, não reinicia nada.
#
# Uso: status.sh --host <ip> --user <deploy> [--app-path /srv/app] [--key <chave>]

set -uo pipefail

HOST=""; USER_NAME="deploy"; PORT=22; KEY_PATH=""; APP_PATH="/srv/app"; SERVICE="sshepherd-app"

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 ;;
    --app-path) APP_PATH="$2"; shift 2 ;;
    --service) SERVICE="$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)

REMOTE=$(cat <<REMOTE_SCRIPT
APP_PATH="${APP_PATH}"; SERVICE="${SERVICE}"
echo "IND|uptime|\$(cut -d. -f1 /proc/uptime 2>/dev/null || echo 0)"
echo "IND|load1|\$(awk '{print \$1}' /proc/loadavg 2>/dev/null)"
echo "IND|cpus|\$(nproc 2>/dev/null || echo 1)"
echo "IND|mem_used_pct|\$(free | awk '/^Mem:/{printf "%.0f", \$3/\$2*100}')"
echo "IND|mem_total_mb|\$(free -m | awk '/^Mem:/{print \$2}')"
echo "IND|disk_used_pct|\$(df -P / | tail -n1 | awk '{gsub("%","",\$5); print \$5}')"
echo "IND|disk_free_mb|\$(df -Pm / | tail -n1 | awk '{print \$4}')"
echo "IND|app_service|\$(systemctl is-active "\$SERVICE" 2>/dev/null || echo ausente)"
echo "IND|web_service|\$(systemctl is-active caddy 2>/dev/null || systemctl is-active nginx 2>/dev/null || echo ausente)"
if command -v ufw >/dev/null 2>&1; then
  sudo -n ufw status 2>/dev/null | grep -qi "Status: active" && echo "IND|firewall|ativo" || echo "IND|firewall|inativo"
else echo "IND|firewall|ausente"; fi
echo "IND|sec_pending|\$(apt-get -s upgrade 2>/dev/null | grep -ci '^Inst.*security' || echo 0)"
echo "IND|release|\$(readlink "\$APP_PATH/current" 2>/dev/null | xargs -r basename || echo nenhuma)"
echo "IND|releases_count|\$(ls -1 "\$APP_PATH/releases" 2>/dev/null | wc -l)"
echo "IND|clock|\$(date -u +%s)"
echo "IND|cert_days|\$(
  for d in /var/lib/caddy/.local/share/caddy/certificates/*/*/*.crt /etc/letsencrypt/live/*/cert.pem; do
    [ -r "\$d" ] || continue
    E=\$(openssl x509 -enddate -noout -in "\$d" 2>/dev/null | cut -d= -f2)
    [ -n "\$E" ] && echo \$(( (\$(date -d "\$E" +%s) - \$(date +%s)) / 86400 )) && break
  done
)"
if [ "\$(df -P / | tail -n1 | awk '{gsub("%","",\$5); print \$5}')" -ge 80 ]; then
  echo "TOP|disco"
  du -xhd1 / 2>/dev/null | sort -rh | head -6 | sed 's/^/TOPDISK|/'
fi
if [ "\$(free | awk '/^Mem:/{printf "%.0f", \$3/\$2*100}')" -ge 80 ]; then
  echo "TOP|memória"
  ps -eo pmem,pcpu,comm --sort=-pmem 2>/dev/null | head -6 | sed 's/^/TOPMEM|/'
fi
if command -v fail2ban-client >/dev/null 2>&1; then
  echo "IND|banidos|\$(sudo -n fail2ban-client status sshd 2>/dev/null | grep -i 'Currently banned' | grep -oE '[0-9]+' | head -n1)"
fi
REMOTE_SCRIPT
)

RAW=$(ssh "${SSH_OPTS[@]}" "${USER_NAME}@${HOST}" "$REMOTE" 2>&1)
if [ $? -ne 0 ]; then
  echo "SERVIDOR INACESSIVEL: ${HOST}" >&2
  printf '%s\n' "$RAW" | sed 's/^/  /' >&2
  echo "" >&2
  echo "Isso já é um diagnóstico: o problema esta antes da aplicação." >&2
  echo "Confira no painel do provedor se a máquina está ligada." >&2
  exit 13
fi

g() { printf '%s\n' "$RAW" | grep "^IND|$1|" | head -n1 | cut -d'|' -f3-; }

UPTIME=$(g uptime); LOAD=$(g load1); CPUS=$(g cpus)
MEM=$(g mem_used_pct); MEMTOTAL=$(g mem_total_mb)
DISK=$(g disk_used_pct); DISKFREE=$(g disk_free_mb)
APPSVC=$(g app_service); WEBSVC=$(g web_service); FW=$(g firewall)
SECP=$(g sec_pending); RELEASE=$(g release); RELCOUNT=$(g releases_count)
CERT=$(g cert_days); BANIDOS=$(g banidos); CLOCK=$(g clock)

ALERTAS=0
line() { # nome valor limite status
  case "$4" in
    normal)  printf '  [ok]   %-24s %-22s (%s)\n' "$1" "$2" "$3" ;;
    atenção) printf '  [!]    %-24s %-22s (%s)\n' "$1" "$2" "$3"; ALERTAS=$((ALERTAS+1)) ;;
    crítico) printf '  [!!!]  %-24s %-22s (%s)\n' "$1" "$2" "$3"; ALERTAS=$((ALERTAS+1)) ;;
  esac
}

st_num() { # valor atenção crítico
  if [ "${1:-0}" -ge "$3" ]; then echo crítico
  elif [ "${1:-0}" -ge "$2" ]; then echo atenção
  else echo normal; fi
}

UPTIME_H=$(( ${UPTIME:-0} / 3600 ))

echo ""
echo "============================================"
echo " ESTADO DO SERVIDOR — ${HOST}"
echo " Modo: somente leitura"
echo "============================================"
echo ""

line "tempo ligado" "${UPTIME_H}h" "informativo" \
  "$([ "${UPTIME_H}" -lt 1 ] && echo atenção || echo normal)"

LOAD_PCT=$(awk -v l="${LOAD:-0}" -v c="${CPUS:-1}" 'BEGIN{printf "%.0f", l/c*100}')
line "carga de processamento" "${LOAD} (${LOAD_PCT}% de ${CPUS} cpu)" "atenção 100, crítico 200" \
  "$(st_num "$LOAD_PCT" 100 200)"

line "memória usada" "${MEM}% de ${MEMTOTAL} MB" "atenção 80, crítico 92" \
  "$(st_num "$MEM" 80 92)"

line "disco usado" "${DISK}% (${DISKFREE} MB livres)" "atenção 80, crítico 90" \
  "$(st_num "$DISK" 80 90)"

line "serviço da aplicação" "${APPSVC}" "esperado: active" \
  "$([ "$APPSVC" = "active" ] && echo normal || echo crítico)"

line "servidor web" "${WEBSVC}" "esperado: active" \
  "$([ "$WEBSVC" = "active" ] && echo normal || echo crítico)"

line "firewall" "${FW}" "esperado: ativo" \
  "$([ "$FW" = "ativo" ] && echo normal || echo atenção)"

line "updates de segurança" "${SECP:-0} pendentes" "atenção 1, crítico 10" \
  "$(st_num "${SECP:-0}" 1 10)"

if [ -n "$CERT" ]; then
  line "certificado" "expira em ${CERT} dias" "atenção abaixo de 15" \
    "$([ "${CERT:-999}" -lt 15 ] && echo atenção || echo normal)"
fi

echo ""
echo "  Informativo:"
echo "    versão ativa      : ${RELEASE:-nenhuma}"
echo "    versões guardadas : ${RELCOUNT:-0}"
[ -n "$BANIDOS" ] && echo "    ips bloqueados    : ${BANIDOS}"

# EC-05: relogio do servidor com desvio distorce qualquer correlacao temporal.
LOCAL_CLOCK=$(date -u +%s)
DRIFT=$(( LOCAL_CLOCK - ${CLOCK:-$LOCAL_CLOCK} ))
[ "${DRIFT#-}" -gt 120 ] && echo "    AVISO: relogio do servidor com ${DRIFT}s de desvio; correlacao por horario fica imprecisa"

if printf '%s\n' "$RAW" | grep -q '^TOPDISK|'; then
  echo ""
  echo "  Maiores consumidores de disco:"
  printf '%s\n' "$RAW" | grep '^TOPDISK|' | cut -d'|' -f2- | sed 's/^/    /'
fi
if printf '%s\n' "$RAW" | grep -q '^TOPMEM|'; then
  echo ""
  echo "  Maiores consumidores de memória:"
  printf '%s\n' "$RAW" | grep '^TOPMEM|' | cut -d'|' -f2- | sed 's/^/    /'
fi

echo ""
echo "============================================"
if [ "$ALERTAS" -eq 0 ]; then
  echo " Nada fora do normal."
else
  echo " ${ALERTAS} indicador(es) fora do normal."
  echo " Para investigar um sintoma específico: /sshp-doctor"
fi
echo "============================================"
echo "ALERTAS=${ALERTAS}"
exit 0
