#!/bin/sh
set -eu

PROGRAM=mtail-install
EXPECTED_TAILSCALE_VERSION=1.102.3
INSTALL_PATH=/usr/local/bin/mtail
UNINSTALL_PATH=/usr/local/sbin/mtail-uninstall
UNIT_PATH=/etc/systemd/system/mtaild.service
LIBEXEC_DIR=/usr/local/libexec/mtail
RUNTIME_TAILSCALE_PATH=$LIBEXEC_DIR/tailscale
RUNTIME_TAILSCALED_PATH=$LIBEXEC_DIR/tailscaled
PREFLIGHT_PATH=$LIBEXEC_DIR/mtaild-preflight
MARK_START_PATH=$LIBEXEC_DIR/mtaild-mark-start
CLEANUP_PATH=$LIBEXEC_DIR/mtaild-cleanup
START_SERVICE=1

fail() {
  printf '%s: erro: %s\n' "$PROGRAM" "$*" >&2
  exit 1
}

usage() {
  cat <<'EOF'
Uso: sudo ./install.sh [--no-start]

Instala o MTail e o serviço mtaild no Linux. Tailscale não está incluído:
tailscale e tailscaled 1.102.3 devem estar instalados no host. Os binários
validados são copiados para o runtime privado do MTail.
EOF
}

require_command() {
  command -v "$1" >/dev/null 2>&1 || fail "dependência ausente: $1"
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    --no-start)
      START_SERVICE=0
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      fail "opção desconhecida: $1"
      ;;
  esac
done

BUNDLE_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)

[ "$(id -u)" -eq 0 ] || fail "execute como root"
[ "$(uname -s)" = Linux ] || fail "somente Linux é suportado"
[ -d /run/systemd/system ] || fail "systemd não está executando neste host"

for dependency in install sed sha256sum systemctl tailscale tailscaled; do
  require_command "$dependency"
done

[ -c /dev/net/tun ] || fail "/dev/net/tun não está disponível; carregue/configure o driver TUN antes de instalar"

for relative_path in \
  mtail install.sh uninstall.sh mtaild.service README.txt CHECKSUMS.sha256 VERSION ARCHITECTURE \
  libexec/mtaild-preflight libexec/mtaild-mark-start libexec/mtaild-cleanup; do
  [ -f "$BUNDLE_DIR/$relative_path" ] || fail "arquivo ausente no pacote: $relative_path"
  [ ! -L "$BUNDLE_DIR/$relative_path" ] || fail "link simbólico proibido no pacote: $relative_path"
done

if ! (cd "$BUNDLE_DIR" && sha256sum -c CHECKSUMS.sha256 >/dev/null); then
  fail "a verificação de integridade do pacote falhou"
fi

case "$(sed -n '1p' "$BUNDLE_DIR/ARCHITECTURE")" in
  linux/amd64) BUNDLE_ARCH=amd64 ;;
  linux/arm64) BUNDLE_ARCH=arm64 ;;
  *) fail "arquitetura inválida no pacote" ;;
esac

case "$(uname -m)" in
  x86_64|amd64) HOST_ARCH=amd64 ;;
  aarch64|arm64) HOST_ARCH=arm64 ;;
  *) fail "arquitetura Linux não suportada: $(uname -m)" ;;
esac
[ "$BUNDLE_ARCH" = "$HOST_ARCH" ] || \
  fail "pacote linux/$BUNDLE_ARCH não corresponde ao host linux/$HOST_ARCH"

[ -x "$BUNDLE_DIR/mtail" ] || fail "o binário MTail do pacote não é executável"
"$BUNDLE_DIR/mtail" help >/dev/null 2>&1 || \
  fail "o binário MTail não executa neste host; baixe o pacote da arquitetura correta"

TAILSCALE_BIN=$(command -v tailscale)
TAILSCALED_BIN=$(command -v tailscaled)
for engine_path in "$TAILSCALE_BIN" "$TAILSCALED_BIN"; do
  case "$engine_path" in
    /*) ;;
    *) fail "o caminho do engine Tailscale deve ser absoluto: $engine_path" ;;
  esac
  case "$engine_path" in
    *[!A-Za-z0-9_./+-]*) fail "o caminho do engine Tailscale contém caracteres não suportados: $engine_path" ;;
  esac
  [ -f "$engine_path" ] || fail "binário do engine não é um arquivo regular: $engine_path"
  [ -x "$engine_path" ] || fail "binário do engine não é executável: $engine_path"
done

TAILSCALE_VERSION=$($TAILSCALE_BIN version 2>/dev/null | sed -n '1p')
[ "$TAILSCALE_VERSION" = "$EXPECTED_TAILSCALE_VERSION" ] || \
  fail "tailscale $EXPECTED_TAILSCALE_VERSION é obrigatório; encontrado: ${TAILSCALE_VERSION:-versão desconhecida}"

TAILSCALED_VERSION=$($TAILSCALED_BIN --version 2>/dev/null | sed -n '1p')
[ "$TAILSCALED_VERSION" = "$EXPECTED_TAILSCALE_VERSION" ] || \
  fail "tailscaled $EXPECTED_TAILSCALE_VERSION é obrigatório; encontrado: ${TAILSCALED_VERSION:-versão desconhecida}"

# Nunca desligamos uma rede existente de forma implícita. Mesmo uma unit apenas
# habilitada disputaria DNS, rotas e netfilter no próximo boot.
if systemctl is-active --quiet tailscaled.service 2>/dev/null || \
   systemctl is-enabled --quiet tailscaled.service 2>/dev/null; then
  fail "tailscaled.service está ativo ou habilitado; após confirmar a migração, execute 'systemctl disable --now tailscaled.service'. Nada foi alterado"
fi

install -d -m 0755 /usr/local/bin /usr/local/sbin "$LIBEXEC_DIR" /etc/systemd/system
install -m 0755 "$BUNDLE_DIR/mtail" "$INSTALL_PATH"
install -m 0755 "$BUNDLE_DIR/uninstall.sh" "$UNINSTALL_PATH"

# Cópias privadas mantêm o engine pinado mesmo após atualizações do gerenciador
# de pacotes. O preflight revalida ambas antes de cada inicialização do daemon.
install -m 0755 "$TAILSCALE_BIN" "$RUNTIME_TAILSCALE_PATH"
install -m 0755 "$TAILSCALED_BIN" "$RUNTIME_TAILSCALED_PATH"
install -m 0755 "$BUNDLE_DIR/libexec/mtaild-preflight" "$PREFLIGHT_PATH"
install -m 0755 "$BUNDLE_DIR/libexec/mtaild-mark-start" "$MARK_START_PATH"
install -m 0755 "$BUNDLE_DIR/libexec/mtaild-cleanup" "$CLEANUP_PATH"
install -m 0644 "$BUNDLE_DIR/mtaild.service" "$UNIT_PATH"
systemctl daemon-reload

if [ "$START_SERVICE" -eq 1 ]; then
  if systemctl is-active --quiet mtaild.service 2>/dev/null; then
    systemctl restart mtaild.service || fail "não foi possível reiniciar mtaild.service"
    systemctl enable mtaild.service >/dev/null || fail "não foi possível habilitar mtaild.service"
  else
    systemctl enable --now mtaild.service || fail "não foi possível habilitar e iniciar mtaild.service"
  fi
  systemctl is-active --quiet mtaild.service 2>/dev/null || \
    fail "mtaild.service não ficou ativo; consulte: journalctl -u mtaild.service"
  printf '%s: MTail %s instalado e mtaild.service ativo\n' "$PROGRAM" "$(sed -n '1p' "$BUNDLE_DIR/VERSION")"
else
  printf '%s: MTail %s instalado; inicie com: systemctl enable --now mtaild.service\n' "$PROGRAM" "$(sed -n '1p' "$BUNDLE_DIR/VERSION")"
fi

printf '%s: para remover, execute: sudo %s\n' "$PROGRAM" "$UNINSTALL_PATH"
