#!/usr/bin/env bash

### PROCEDIMENTOS MANUAIS
# - root password
# - sources.list
# - firmwares
# - network/interfaces

USER="rcaldas"
NAME_USER="Robson Caldas"
HOME_USER="/var/$USER"
MAIL_USER="rclgsm@gmail.com"
DOMAIN="rcaldas.com"

SSH_PORT="8422"

BIN_DIR="/usr/local/bin"
SYNC_BIN="$HOME_USER/live/bin"
SYNC_HOME="$HOME_USER/live/home"

MAIL_ADMIN="rclgsm@gmail.com"

WALLPAPER="https://rcaldas.com/wallpapers/00.jpg"

# Arquitetura do SISTEMA, nao do chip -- e' a distincao que importa: um
# Rock64 e' ARMv8 (64-bit) mas rodando Armbian armhf o userland e' 32-bit e
# o dpkg reporta "armhf". Quem decide qual binario instalar e' o dpkg, nao
# o "uname -m". Detectado uma vez e reusado no resto do script.
DPKG_ARCH="$(dpkg --print-architecture 2>/dev/null || echo amd64)"

# O fastfetch publica um .deb por arquitetura, e os nomes NAO batem com os
# do dpkg: aarch64 (nao arm64) e armv7l (nao armhf).
case "$DPKG_ARCH" in
  amd64) FASTFETCH_ARCH="amd64" ;;
  arm64) FASTFETCH_ARCH="aarch64" ;;
  armhf) FASTFETCH_ARCH="armv7l" ;;
  *)     FASTFETCH_ARCH="" ;;
esac
FASTFETCH_URL="https://github.com/fastfetch-cli/fastfetch/releases/latest/download/fastfetch-linux-$FASTFETCH_ARCH.deb"

# A Mozilla so' publica tarball oficial pra x86_64 -- nao existe build ARM.
# Em ARM o caminho e' o firefox-esr da distro; ver o bloco de desktop.
FIREFOX_URL="https://download.mozilla.org/?product=firefox-latest-ssl&os=linux64&lang=pt-BR"

default_apps="sudo rsync curl tmux python3-pip openssh-server dnsutils wget \
  iperf3 sed git bash-completion pv net-tools nftables chrony fio \
  nmap iputils-ping ipvsadm unattended-upgrades jq htop iotop sysstat \
  ca-certificates apt-transport-https lsb-release debian-goodies"

  # gnupg2
  # shim-signed
  # qemu-guest-agent
  # amd64-microcode
  # intel-microcode

  # firmware-linux-nonfree firmware-ipw2x00 firmware-bnx2x firmware-intel-sound \
  # firmware-brcm80211 firmware-intelwimax firmware-libertas firmware-atheros \
  # firmware-amd-graphics firmware-ralink firmware-realtek firmware-iwlwifi \

  # lightdm lightdm-gtk-greeter mate-desktop-environment-extras

desktop_apps="iotop iftop hdparm zip unzip unrar-free p7zip findutils \
              build-essential gparted ntfs-3g xdg-utils redshift-gtk \
              autotools-dev autoconf g++ \
              gnupg2 gnupg-agent cups system-config-printer printer-driver-all \
              openprinting-ppds hp-ppd vlc x11vnc \
              pavucontrol network-manager gnome-terminal \
              cputool tlp ruby-notify sg3-utils"

RESOLV_CONF=$(cat <<EOF
search rcaldas.com
nameserver 8.8.4.4
nameserver 1.0.0.1
nameserver 2620:0:ccc::2
EOF
)

### Check Root
[ $(id -u) = 0 ] || {
  echo -e "\nNot root.\nExiting."
  exit 1
}

### Helper App Installer
function package_installer(){
  [[ -z $1 ]] && {
    echo "Need packages as argument"; return
  }
  for_install=''
  for p in $1; do
    if ! dpkg -s "$p" &> /dev/null; then
      for_install=$for_install' '$p
    fi
  done
  [ -z "$for_install" ] || {
    apt-get update > /dev/null
    DEBIAN_FRONTEND=noninteractive apt-get -qq --allow-change-held-packages install $for_install > /dev/null
    apt-get -qq clean
  }
  if ! dpkg -s fastfetch &> /dev/null; then
    # O fastfetch serve so' pra ficha do host (job host-info). Nao pode
    # derrubar o provisionamento inteiro se faltar build pra arquitetura --
    # por isso cada passo aqui tolera falha explicitamente.
    if [ -n "$FASTFETCH_ARCH" ]; then
      if curl -fsSL "$FASTFETCH_URL" -o /tmp/fastfetch.deb 2>/dev/null \
         && dpkg -i /tmp/fastfetch.deb > /dev/null 2>&1; then
        apt install -yf > /dev/null 2>&1 || true
      else
        # Tenta o da distro antes de desistir: em ARM costuma existir.
        DEBIAN_FRONTEND=noninteractive apt-get -qq install fastfetch > /dev/null 2>&1 \
          || echo "  AVISO: fastfetch indisponivel para $DPKG_ARCH -- seguindo sem ele"
      fi
      rm -f /tmp/fastfetch.deb
    else
      DEBIAN_FRONTEND=noninteractive apt-get -qq install fastfetch > /dev/null 2>&1 \
        || echo "  AVISO: arquitetura $DPKG_ARCH sem build de fastfetch -- pulando"
    fi
  fi
}

### Ask options
function ask_user(){
  read < /dev/tty -rep $'\n[USER] Change user?\n['$USER$']> ' NEWUSER
  if [[ -n $NEWUSER ]]; then
    USER=$NEWUSER
  fi

  read < /dev/tty -rep $'\n[USER] Change username?\n['"$NAME_USER"$']> ' NEWNAME_USER
  if [[ -n $NEWNAME_USER ]]; then
    NAME_USER=$NEWNAME_USER
  fi

  read < /dev/tty -rep $'\n[USER] Change user home?\n['$HOME_USER$']> ' NEWHOME_USER
  if [[ -n $NEWHOME_USER ]]; then
    HOME_USER=$NEWHOME_USER
  fi
}

function asks(){
  read < /dev/tty -rep $'\n[HOSTNAME] Change hostname?\n['$HOSTNAME$']> ' NEWHOSTNAME

  read < /dev/tty -rep $'\n[DNS] DNS Static or Dynamic\n(s/d)> ' SETDNS

  read < /dev/tty -rep $'\n[SSH] Change SSH Config (port and match user)?\n(Y/n)> ' CHANGESSH

  read < /dev/tty -rep $'\n[SYNCTHING] Install syncthing?\n(y/N)> ' INSTSYNC

  read < /dev/tty -rep $'\n[DOCKER] Install Docker?\n(y/N)> ' INSTDOCKER

  read < /dev/tty -rep $'\n[DESKTOP] It\'s a Desktop?\n(y/N)> ' ISDESKTOP
}

function set_hostname(){
    echo hostname
    echo "$NEWHOSTNAME" > /etc/hostname
    hostname -F /etc/hostname
    HOSTNAME=$NEWHOSTNAME
    sed -i "/^127.0.0.1/c\127.0.0.1\tlocalhost" /etc/hosts
    grep -q "127.0.1.1" /etc/hosts && \
      sed -i "/^127.0.1.1/c\127.0.1.1\t$HOSTNAME.$DOMAIN\t$HOSTNAME" /etc/hosts || \
      sed -i "0,/localhost/s//localhost\n127.0.1.1\t$HOSTNAME.$DOMAIN\t$HOSTNAME/" /etc/hosts
}

function set_dns(){
  if [ "$SETDNS" == "S" ] || [ "$SETDNS" == "s" ]; then
    echo static_dns
    DEBIAN_FRONTEND=noninteractive apt-get -qq purge resolvconf rdnssd &> /dev/null
    systemctl disable --now systemd-resolved &> /dev/null
    systemctl disable --now resolvconf &> /dev/null
    if [ -d /etc/dhcp/dhclient-enter-hooks.d ]; then
      echo -e '#!/bin/sh\nmake_resolv_conf(){ : ; }' > /etc/dhcp/dhclient-enter-hooks.d/nodnsupdate
      chmod +x /etc/dhcp/dhclient-enter-hooks.d/nodnsupdate
    fi
    if [ -d /etc/NetworkManager/conf.d ]; then
      echo -e "[main]\ndns=none" > /etc/NetworkManager/conf.d/no-dns.conf
      # RECARREGAR antes de gravar o resolv.conf, e nao depois. O NM so' le
      # essa config na subida: sem o reload ele continua se achando dono do
      # arquivo e reescreve por cima do que gravamos abaixo. O sintoma e um
      # /etc/resolv.conf com apenas "# Generated by NetworkManager" e
      # nenhum nameserver -- host sem DNS, como aconteceu no d7.
      systemctl reload NetworkManager &> /dev/null || systemctl restart NetworkManager &> /dev/null || true
    fi
    rm -rf /etc/resolv.conf
    echo -e "$RESOLV_CONF" > /etc/resolv.conf
    # Confere em vez de torcer: se algo reescreveu por cima, avisa agora,
    # enquanto alguem esta olhando o output do /init.
    grep -q '^nameserver' /etc/resolv.conf 2>/dev/null || \
      echo "  AVISO: /etc/resolv.conf ficou sem nameserver -- algo reescreveu por cima"
  elif [ "$SETDNS" == "D" ] || [ "$SETDNS" == "d" ]; then
    echo dynamic_dns
    systemctl enable systemd-resolved &> /dev/null
    rm -f /etc/dhcp/dhclient-enter-hooks.d/nodnsupdate /etc/NetworkManager/conf.d/no-dns.conf &> /dev/null
  fi
}

function set_timezone(){
  echo timezone
  echo "America/Sao_Paulo" > /etc/timezone
  ln -sf /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime
  echo -e "en_US.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8" > /etc/locale.gen
  locale -a | grep -q "pt_BR.utf8" || /usr/sbin/locale-gen > /dev/null
  locale -a | grep -q "en_US.utf8" || /usr/sbin/locale-gen > /dev/null
}

function set_packages(){
  echo packages
  package_installer "$default_apps"

  cat <<'EOF' > /etc/apt/apt.conf.d/02periodic
APT::Periodic::Enable "1";
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "5";
APT::Periodic::Verbose "0";
EOF
  cat <<EOF > /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Origins-Pattern {
  "origin=Debian";
};
//    "always", "only-on-error" or "on-change"
Unattended-Upgrade::MailReport "only-on-error";
Unattended-Upgrade::Mail "$MAIL_ADMIN";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
EOF
}

function set_ssh(){
  echo ssh
  grep -q "Port " /etc/ssh/sshd_config && {
    sed -i "s/#*Port\s.*$/Port $SSH_PORT/" /etc/ssh/sshd_config
    } || sed -i "1iPort $SSH_PORT" /etc/ssh/sshd_config

  grep -q "Match User $USER" /etc/ssh/sshd_config || \
    echo -e "Match User $USER\n\tX11Forwarding yes\n\tAllowTcpForwarding yes\n\tGatewayPorts yes" \
      >> /etc/ssh/sshd_config

  > /etc/motd
  > /etc/issue
  > /etc/issue.net
  systemctl enable ssh &> /dev/null || update-rc.d ssh enable &> /dev/null
  systemctl restart ssh &> /dev/null || /etc/init.d/ssh restart &> /dev/null
}

function set_fail2ban(){
  echo fail2ban
  package_installer "fail2ban"
  # Se o host ja tem jail.local com um [sshd] proprio, nao encosta: sao
  # valores ajustados a mao que nao devem ser atropelados. Precedencia do
  # fail2ban e traicoeira -- [sshd] no nosso jail.d perde pro [sshd] do
  # jail.local, mas GANHA do [DEFAULT] dele. Ja aconteceu de afrouxar um
  # bantime de 1 dia pra 1 hora sem ninguem perceber.
  if grep -qs '^\[sshd\]' /etc/fail2ban/jail.local; then
    echo "  jail.local ja tem [sshd] proprio -- preservando"
  else
    cat > /etc/fail2ban/jail.d/rcaldas-sshd.conf <<EOF
[sshd]
enabled = true
port = $SSH_PORT
maxretry = 5
findtime = 10m
bantime = 1h
EOF
  fi
  systemctl enable fail2ban &> /dev/null
  # restart --now-if-failed: se a config do host tiver algum jail quebrado
  # (ex: logpath que mudou de lugar), o restart derruba o fail2ban inteiro
  # e o host fica sem protecao nenhuma. Avisa alto em vez de sair calado.
  if ! systemctl restart fail2ban &> /dev/null; then
    echo "  AVISO: fail2ban NAO subiu -- host sem protecao. Ver: journalctl -u fail2ban"
  fi
}

function ensure_root_key(){
  echo ssh-root-key
  if [[ ! -f /root/.ssh/id_ed25519.pub ]] && ! ls /root/.ssh/id_*.pub &> /dev/null; then
    yes '' | ssh-keygen -qt ed25519 -N '' > /dev/null
  fi
  PUBKEY=$(cat /root/.ssh/id_ed25519.pub 2>/dev/null || cat /root/.ssh/id_*.pub 2>/dev/null | head -1)
  echo -e "\nChave publica do root: $PUBKEY\n"

  if curl -fsS -m 15 -H 'Content-Type: application/json' -X POST "https://web.rcaldas.com/api/register-tunnel-key" \
      -d "{\"host\":\"$HOSTNAME\",\"publicKey\":\"$PUBKEY\",\"provisionToken\":\"Wpa7gmyvkx_3A_Ko19fxqWQjFkUhZJdDLGdWz78Z3gY\"}" > /dev/null 2>&1; then
    echo "Pedido de tunel registrado -- aguardando aprovacao por email antes do tunel funcionar."
  else
    echo "Nao foi possivel registrar o pedido de tunel automaticamente -- avise o admin com a chave acima."
  fi
}

function set_local_mail(){
  echo mail-local

  # SEM postfix e SEM relay pro Mailu -- de proposito. O Mailu e' um servico
  # em Docker, independente; nao faz sentido ser dependencia de
  # provisionamento de host. O sendmail deste host e' o shim que o /install
  # instala, que joga o mail local no journal -> coletor central -> Loki.
  #
  # Por que abandonar email: ele falha calado. O zed do ZFS estava
  # configurado com o endereco certo e mesmo assim um disco com erro de I/O
  # passou 3 dias despercebido, porque a entrega nao acontecia. E o proprio
  # us acumulou 17 mensagens presas na fila por dias sem ninguem saber.
  #
  # O pacote mailutils fica: o binario 'mail' e' o que varias coisas chamam (o zed
  # e' uma delas), e ele entrega via sendmail -- que agora e' o shim.
  package_installer "mailutils"

  # MAILTO precisa estar DEFINIDO, mesmo agora. Com MAILTO vazio o cron
  # descarta a saida do job em silencio, sem sequer invocar o sendmail --
  # e' exatamente o que a gente NAO quer perder. O endereco em si nao
  # importa: o shim ignora destinatario.
  grep -q 'MAILTO=' /etc/crontab && \
    sed -i "/MAILTO=/c\MAILTO=root" /etc/crontab || \
    sed -i "1iMAILTO=root" /etc/crontab
}

function set_backup_access(){
  echo backup-access
  RUNNER_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKZNqe/xQr59cm8NQhqUKNVbldA9ujOHgFmZsY9Q1q5F backup-runner@bag"
  if [[ -z "$RUNNER_KEY" ]]; then
    echo "  (sem chave de runner publicada -- backup deste host nao vai funcionar ate haver uma)"
    return
  fi

  AUTH="$HOME_USER/.ssh/authorized_keys"
  [[ -d $HOME_USER/.ssh ]] || return

  # Idempotente: se a chave ja esta la, nao duplica. Sem restrict/command:
  # o backup precisa rodar 'sudo rsync' no destino pra ler arquivo de root,
  # e um forced command com rrsync nao eleva privilegio -- mesma escolha
  # que o us.bkp que ja funciona (--rsync-path="sudo /usr/bin/rsync").
  if grep -qsF "$RUNNER_KEY" "$AUTH"; then
    echo "  chave do runner ja autorizada"
  else
    echo "$RUNNER_KEY" >> "$AUTH"
    chown $USER: "$AUTH" 2>/dev/null || true
    chmod 600 "$AUTH" 2>/dev/null || true
    echo "  chave do runner autorizada em $AUTH"
  fi
}

function set_user(){
  echo user
  if grep -q "^$USER:" /etc/passwd; then
    usermod -md "$HOME_USER" "$USER" &> /dev/null
    usermod -aG sudo,dialout -g adm -c \""$NAME_USER"\" -s /bin/bash -u 8484 "$USER" &> /dev/null
  else
    useradd -N -G sudo,dialout -g adm -md "$HOME_USER" -c \""$NAME_USER"\" -s /bin/bash -u 8484 "$USER" &> /dev/null
  fi

  [[ -d $HOME_USER/.ssh ]] || su - $USER -c "mkdir $HOME_USER/.ssh"

  [[ -f $HOME_USER/.ssh/id_ed25519.pub ]] || {
    su - $USER -c "yes '' | ssh-keygen -qt ed25519 -N '' > /dev/null"
  }

  # Bin: se o Syncthing local ja tiver sincronizado $SYNC_BIN neste host,
  # usa link simbolico (fica ao vivo, acompanha futuras mudancas). Senao,
  # usa o conteudo atual servido pelo /init direto do servidor central.
  # Checar isso de novo a cada execucao evita perder os links se o /init
  # for rodado de novo depois que o Syncthing ja estiver configurado aqui.
  # A condicao testa se ha ARQUIVO, nao so' se o diretorio existe. Com o
  # teste antigo (-d apenas), um $SYNC_BIN vazio -- Syncthing instalado mas
  # ainda sem sincronizar, ou diretorio criado a mao -- fazia o script
  # entrar aqui, iterar sobre nada e nao gravar coisa nenhuma.
  if [[ -d $SYNC_BIN ]] && [[ -n "$(find "$SYNC_BIN" -type f -print -quit 2>/dev/null)" ]]; then
    for i in $(find "$SYNC_BIN" -type f); do
      rm "$BIN_DIR""${i#$SYNC_BIN}" &> /dev/null
      ln -sf "$i" "$BIN_DIR""${i#$SYNC_BIN}"
      chmod +x "$i"
    done
  else
    cat <<'BINFILE_0_EOF' > "$BIN_DIR"/bndes
#!/bin/bash
# ~/live/bin/bndes (versão Remmina)
#
# Uso:
#   bndes                       -> pega o .rdp mais recente em ~/Downloads
#   bndes /caminho/arquivo.rdp  -> usa o arquivo passado (duplo clique)

if [ -n "$1" ]; then
    ARQUIVO="$1"
else
    DOWNLOADS="$HOME/Downloads"
    ARQUIVO=$(ls -t "$DOWNLOADS"/launch*.rdp 2>/dev/null | head -n1)
fi

if [ -z "$ARQUIVO" ] || [ ! -f "$ARQUIVO" ]; then
    notify-send "RDP Trabalho" "Nenhum arquivo .rdp encontrado." 2>/dev/null
    exit 1
fi

# Trava por arquivo: evita que um disparo duplo (ou clique repetido) gaste
# o token do gateway duas vezes.
LOCKFILE="/tmp/rdp-lock-$(basename "$ARQUIVO").lock"
exec 9>"$LOCKFILE"
if ! flock -n 9; then
    notify-send "RDP Trabalho" "Já existe uma tentativa de conexão em andamento para este arquivo." 2>/dev/null
    exit 0
fi

unset https_proxy http_proxy HTTPS_PROXY HTTP_PROXY

# Injeta as configurações no .rdp, só se ainda não existirem
grep -q "^audiomode:" "$ARQUIVO"         || echo "audiomode:i:0"          >> "$ARQUIVO"
grep -q "^username:" "$ARQUIVO"          || echo "username:s:robca"       >> "$ARQUIVO"
grep -q "^domain:" "$ARQUIVO"            || echo "domain:s:bndes"         >> "$ARQUIVO"
grep -q "^redirectclipboard:" "$ARQUIVO" || echo "redirectclipboard:i:1"  >> "$ARQUIVO"

setsid remmina -c "$ARQUIVO" < /dev/null > /dev/null 2>&1 &
disown

BINFILE_0_EOF
chmod +x "$BIN_DIR"/bndes
cat <<'BINFILE_1_EOF' > "$BIN_DIR"/bndes-xfreerdp
#!/bin/bash
# ~/bin/rdp-trabalho.sh
#
# Uso:
#   rdp-trabalho.sh                       -> pega o .rdp mais recente em ~/Downloads
#   rdp-trabalho.sh /caminho/arquivo.rdp  -> usa o arquivo passado (duplo clique)

if [ -n "$1" ]; then
    ARQUIVO="$1"
else
    DOWNLOADS="$HOME/Downloads"
    ARQUIVO=$(ls -t "$DOWNLOADS"/launch*.rdp 2>/dev/null | head -n1)
fi

if [ -z "$ARQUIVO" ] || [ ! -f "$ARQUIVO" ]; then
    notify-send "RDP Trabalho" "Nenhum arquivo .rdp encontrado." 2>/dev/null
    exit 1
fi

# Trava por arquivo: evita que um disparo duplo (ou clique repetido) gaste
# o token do gateway duas vezes.
LOCKFILE="/tmp/rdp-lock-$(basename "$ARQUIVO").lock"
exec 9>"$LOCKFILE"
if ! flock -n 9; then
    notify-send "RDP Trabalho" "Já existe uma tentativa de conexão em andamento para este arquivo." 2>/dev/null
    exit 0
fi

unset https_proxy http_proxy HTTPS_PROXY HTTP_PROXY

if ! command -v zenity >/dev/null; then
    notify-send -u critical "RDP Trabalho" "zenity não instalado. Rode: sudo apt install zenity" 2>/dev/null
    exit 1
fi

SENHA=$(zenity --password --title="Senha de rede (bndes\\robca)" 2>/dev/null)
if [ -z "$SENHA" ]; then
    exit 0
fi

LOGFILE="$HOME/rdp-log-$(date +%Y%m%d-%H%M%S).txt"

setsid bash -c '
    ARQUIVO="$1"
    LOGFILE="$2"
    SENHA="$3"

    printf "%s\n%s\n" "$SENHA" "$SENHA" | xfreerdp3 "$ARQUIVO" \
        /u:robca /d:bndes \
        /from-stdin:force \
        /sound:sys:pulse /audio-mode:0 \
        /size:1600x900 \
        +dynamic-resolution \
        +decorations \
        -grab-keyboard
        #> "$LOGFILE" 2>&1
    STATUS=$?

    if [ $STATUS -ne 0 ]; then
        ERRO=$(grep -oP "(?<=\[ERROR\]\[).*" "$LOGFILE" | tail -n1)
        notify-send -u critical "RDP falhou" "Conexão não estabelecida.
${ERRO}" 2>/dev/null
    fi
' _ "$ARQUIVO" "$LOGFILE" "$SENHA" < /dev/null &
disown


BINFILE_1_EOF
chmod +x "$BIN_DIR"/bndes-xfreerdp
cat <<'BINFILE_2_EOF' > "$BIN_DIR"/como
#!/usr/bin/env bash
### Manuais "como"
set -e

COMO="/var/rcaldas/live/como"

function help() {
  if [ -n "$1" ]; then
    echo -e "$1"
    exit 9
  else
    echo -e "\\n### COMO
Para editar ou adicionar: 'como -e <man>'
Para criar uma diretorio: 'como -d <man>'
Para baixar um site para o diretório atual: 'como webclone <URL>'
Para instalar o COMO no sistema: 'como -i'
\\nLista de manuais existente:\\n\\n$(ls $COMO)\\n
" | less
    exit 9
  fi
}

[ -r $COMO ] || help "Não foi possivel encontrar biblioteca do 'como'"

function como_edit() {
  [ -n "$1" ] && EFILE="$1" ||
    read -rp "Digite o nome do arquivo para editar ou criar: " EFILE
  nano "$COMO/$EFILE"
  # atom-beta "$COMO/$EFILE" || nano "$COMO/$EFILE"
  exit 0
}
function como_dir() {
  [ -n "$1" ] && EDIR="$1" ||
    read -rp "Digite o nome do diretório: " EDIR
  [ -r "$COMO/$EDIR" ] || mkdir -p "$COMO/$EDIR"
  cd "$COMO/$EDIR" || help "Falha ao acessar diretorio \"$COMO/$EDIR\""
  exec bash
  exit 0
}
function webclone() {
   [ -z "$1" ] && help "\nDigite uma URL como parametro do webclone.\n"
   dpkg -s httrack &> /dev/null || \
     bash -c "sudo apt-get update && sudo apt-get install -y httrack"
   echo $1 > .url # Salva a url para posterior atualizaçao
   httrack $1 -O . -r2 -%e1 -n # Baixa para a pasta atual a pagina simples
   exit 0
}

case $1 in
  "-e") como_edit "$2" ;;
  "-d") como_dir "$2" ;;
  "webclone") webclone "$2" ;;
esac

#shopt -s nullglob # Para nao dar erro se o 'for' abaixo retornar nada
for j in "$COMO"/* ; do
  if [[ $1 == "${j##*/}" ]]; then
    if [ -f "$COMO/$1" ]; then
      more "$COMO/$1"
    elif [ -f "$COMO"/"$1"/index.html ]; then
      xdg-open "$COMO/$1/index.html"
    else xdg-open "$COMO/$1"
    fi
    exit 0
  fi
done
help

BINFILE_2_EOF
chmod +x "$BIN_DIR"/como
cat <<'BINFILE_3_EOF' > "$BIN_DIR"/debian.install
#!/bin/bash
# Instalação Debian Trixie - SSD portátil M2 (multi-PC compatível)
# Corrigido: EFI 512M, trixie, discard/noatime, LVM percentual, senha segura

set -e  # para no primeiro erro

hostname=tp
disk=/dev/sdb   # ajuste para /dev/nvme0n1 se for instalar no NVMe interno

# Detecta sufixo de partição: NVMe/mmcblk usam "p1,p2..", sdX/vdX usam "1,2.." direto
if [[ "$disk" =~ nvme|mmcblk ]]; then
  partsuffix="p"
else
  partsuffix=""
fi
part() { echo "${disk}${partsuffix}${1}"; }   # uso: $(part 4) -> /dev/nvme0n1p4 ou /dev/sdb4

# Senha root pedida interativamente (não fica salva no script/histórico)
read -s -p "Senha root: " rootpwd
echo

### ============ PARTICIONAMENTO ============
gdisk "$disk"
# o
# n / +1M / ef02 (BIOS boot)
# x / a / 2 (flag LegacyBIOSBootable) / m
# n / +512M / ef00 (EFI)   <-- era 50M, causava erro de espaço no fwupd
# n / +30G / 8300           <-- partição raiz
# n / (Enter, Enter) / 8300 <-- FALTAVA: resto do disco p/ container LUKS (vira sdX4)
# w

partprobe

### ============ LUKS + LVM ============
cryptsetup luksFormat "$(part 4)"
cryptsetup open "$(part 4)" TP
pvcreate /dev/mapper/TP
vgcreate tp /dev/mapper/TP

# Percentual em vez de tamanho fixo -> adapta a discos de tamanhos diferentes
lvcreate -l 90%FREE -n var tp
# lvcreate -L 400G -n var tp
lvcreate -l 100%FREE -n swap tp

mkfs.ext4 /dev/tp/var
mkswap /dev/tp/swap

### ============ DEBOOTSTRAP ============
apt install grml-debootstrap

grml-debootstrap -r trixie -t "$(part 3)" --grub "$disk" --efi "$(part 2)" \
  --contrib --non-free \
  --hostname "$hostname" --password "$rootpwd"
 
### ============ MOUNT ============
mount "$(part 3)" /mnt
mount "$(part 2)" /mnt/boot/efi
for i in /proc /dev /sys; do mount -B $i /mnt$i; done

mkdir -p /aux
mount /dev/tp/var /aux
rsync -av --delete /mnt/var/ /aux/
umount /aux
rm -r /mnt/var/*
mount /dev/tp/var /mnt/var

### ============ CHROOT ============
chroot /mnt /bin/bash <<'CHROOT_EOF'
 
# grml-debootstrap antigo não conhece o componente non-free-firmware (Trixie/Bookworm)
# então garantimos manualmente no sources.list antes de instalar os firmwares
sed -i 's/main contrib non-free$/main contrib non-free non-free-firmware/' /etc/apt/sources.list
sed -i 's/main contrib non-free$/main contrib non-free non-free-firmware/' /etc/apt/sources.list.d/*.list 2>/dev/null || true
 
apt update
 
# Pacotes base + firmware (nomes atualizados p/ Trixie)
# cryptsetup-initramfs é ESSENCIAL: sem ele o initramfs não sabe abrir o LUKS
# do /var e swap no boot (crypttab sozinho não basta, precisa do hook)
apt install -y sudo rsync curl bash-completion shim-signed intel-microcode \
  cryptsetup cryptsetup-initramfs \
  firmware-linux firmware-iwlwifi firmware-realtek firmware-amd-graphics \
  firmware-atheros firmware-brcm80211 firmware-misc-nonfree \
  apt-transport-https ca-certificates gnupg2
 
apt install -y cinnamon-desktop-environment task-cinnamon-desktop lightdm
 
CHROOT_EOF

### ============ CRYPTTAB (com discard p/ TRIM do SSD) ============
echo -e "TP\tUUID=$(blkid | grep "$(basename "$(part 4)")" | cut -d'"' -f2)\tnone\tluks,discard" > /mnt/etc/crypttab

### ============ FSTAB (com noatime p/ reduzir escrita no SSD) ============
{
  echo -e "UUID=$(blkid -s UUID -o value "$(part 2)")\t/boot/efi\tvfat\tumask=0077\t\t0\t1"
  echo -e "UUID=$(blkid -s UUID -o value "$(part 3)")\t/\text4\tdefaults,noatime,errors=remount-ro\t0\t1"
  echo -e "UUID=$(blkid | grep m2-var | grep -o 'UUID="[^"]*"' | cut -d'"' -f2)\t/var\text4\tdefaults,noatime,errors=remount-ro\t0\t2"
  echo -e "UUID=$(blkid | grep m2-swap | grep -o 'UUID="[^"]*"' | cut -d'"' -f2)\tnone\tswap\tsw\t0\t0"
  echo -e "proc\t/proc\tproc\tdefaults\t0\t0"
  echo -e "/dev/cdrom\t/mnt/cdrom\tiso9660\tro,user,noauto\t0\t0"
} > /mnt/etc/fstab

### ============ GRUB (dentro do chroot novamente p/ ver blkid montado) ============
chroot /mnt /bin/bash <<CHROOT_EOF2
 
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=M2 "$disk"
efibootmgr -c -d "$disk" -p 2 -l '\EFI\M2\grubx64.efi' -L "M2"
 
update-initramfs -k all -u
 
mkdir -p /boot/efi/EFI/BOOT
cp /boot/efi/EFI/M2/grubx64.efi /boot/efi/EFI/BOOT/BOOTX64.EFI
rm -rf /boot/efi/EFI/debian
 
grub-install --target=i386-pc --recheck "$disk"
 
apt remove -y os-prober
update-grub
 
CHROOT_EOF2

### ============ DESMONTAGEM ============
for i in /proc /dev /sys; do umount /mnt$i; done
umount /mnt/boot/efi
umount /mnt/var
umount /mnt
vgchange -an
cryptsetup close TP

echo "Instalação concluída."

# Limpa a senha da memória do shell
unset rootpwd
BINFILE_3_EOF
chmod +x "$BIN_DIR"/debian.install
cat <<'BINFILE_4_EOF' > "$BIN_DIR"/format_sd.sh
#!/usr/bin/env bash
# Formata SD card / dispositivo flash com exFAT otimizado para desempenho
# Alinhamento: 4MiB | Cluster: recomendação SD Association | blkdiscard antes de formatar
#
# Uso: ./format_sd.sh [dispositivo]
# Exemplo: ./format_sd.sh /dev/sdb

DEVICE="${1:-/dev/mmcblk0}"

# ==================== Verificações ====================
if [[ $EUID -ne 0 ]]; then
    echo "ERRO: Execute como root (sudo $0 $DEVICE)"
    exit 1
fi

if [[ ! -b "$DEVICE" ]]; then
    echo "ERRO: $DEVICE não é um dispositivo de bloco"
    exit 1
fi

# ==================== Info do dispositivo ====================
SIZE_BYTES=$(lsblk -b -d -o SIZE "$DEVICE" | tail -1 | tr -d ' ')
SIZE_GB=$((SIZE_BYTES / 1024 / 1024 / 1024))
MODEL=$(lsblk -d -o MODEL "$DEVICE" 2>/dev/null | tail -1 | xargs)
TRAN=$(lsblk -d -o TRAN "$DEVICE" 2>/dev/null | tail -1 | xargs)

echo "=== Formatação exFAT Otimizada ==="
echo "Dispositivo : $DEVICE"
echo "Modelo      : ${MODEL:-desconhecido}"
echo "Interface   : ${TRAN:-desconhecida}"
echo "Tamanho     : ${SIZE_GB} GB (${SIZE_BYTES} bytes)"
echo ""

# ==================== Cluster size (SD Association spec) ====================
# https://www.sdcard.org/developers/overview/exfat/
if [[ $SIZE_GB -ge 256 ]]; then
    CLUSTER_SIZE=262144   # 256 KB  (>= 256 GB)
elif [[ $SIZE_GB -ge 64 ]]; then
    CLUSTER_SIZE=131072   # 128 KB  (64 GB – 255 GB)
elif [[ $SIZE_GB -ge 32 ]]; then
    CLUSTER_SIZE=65536    #  64 KB  (32 GB – 63 GB)
else
    CLUSTER_SIZE=32768    #  32 KB  (< 32 GB)
fi
CLUSTER_KB=$((CLUSTER_SIZE / 1024))

echo "Cluster size: ${CLUSTER_KB} KB"
echo "Alinhamento : 4 MiB (erase block boundary)"
echo ""

# ==================== Partições montadas? ====================
MOUNTED=$(grep "^${DEVICE}" /proc/mounts | awk '{print $1}')
if [[ -n "$MOUNTED" ]]; then
    echo "Partições montadas detectadas:"
    echo "$MOUNTED"
    echo ""
    read -p "Desmontar automaticamente? (yes/no): " UMOUNT_CONFIRM
    if [[ "$UMOUNT_CONFIRM" == "yes" ]]; then
        for part in $MOUNTED; do
            umount "$part" && echo "  Desmontado: $part"
        done
    else
        echo "Cancele a montagem manualmente e execute novamente."
        exit 1
    fi
fi

# ==================== Confirmação ====================
echo ""
echo "╔════════════════════════════════════════════════════╗"
echo "║  !!! ATENÇÃO: TODOS OS DADOS SERÃO APAGADOS !!!   ║"
echo "║  Dispositivo: $DEVICE                              "
echo "╚════════════════════════════════════════════════════╝"
echo ""
read -p "Digite 'yes' para confirmar a formatação: " CONFIRM
[[ "$CONFIRM" != "yes" ]] && echo "Cancelado." && exit 0

echo ""
START_TIME=$(date +%s)

# ==================== blkdiscard ====================
echo "[1/4] Descartando blocos (blkdiscard) ..."
if blkdiscard "$DEVICE" 2>/dev/null; then
    echo "  OK — blocos descartados (controlador flash resetado)"
else
    echo "  AVISO: blkdiscard não suportado — ignorando (não crítico)"
fi

# ==================== Tabela de partições ====================
echo ""
echo "[2/4] Criando tabela MBR (msdos) ..."
parted "$DEVICE" --script mklabel msdos
echo "  OK"

# ==================== Partição alinhada em 4MiB ====================
echo ""
echo "[3/4] Criando partição exFAT alinhada em 4 MiB ..."
parted "$DEVICE" --script mkpart primary 4MiB 100%
parted "$DEVICE" --script set 1 lba on   # LBA flag necessário para exFAT/FAT em MBR
partprobe "$DEVICE"
sleep 1

# Determinar nome da partição (sdb -> sdb1, mmcblk0 -> mmcblk0p1)
if [[ "$DEVICE" =~ [0-9]$ ]]; then
    PARTITION="${DEVICE}p1"
else
    PARTITION="${DEVICE}1"
fi

if [[ ! -b "$PARTITION" ]]; then
    echo "ERRO: partição $PARTITION não encontrada após partprobe"
    exit 1
fi

echo "  OK — partição: $PARTITION"
echo "  Alinhamento verificado:"
PART_START=$(parted "$DEVICE" --script unit MiB print | grep "^ 1" | awk '{print $2}')
echo "    Início: $PART_START"

# ==================== mkfs.exfat ====================
echo ""
echo "[4/4] Formatando com exFAT (cluster ${CLUSTER_KB} KB) ..."
mkfs.exfat -c "$CLUSTER_SIZE" -n "STORAGE" "$PARTITION"

# ==================== Resumo ====================
END_TIME=$(date +%s)
ELAPSED=$((END_TIME - START_TIME))

echo ""
echo "=== Formatação concluída em ${ELAPSED}s ==="
echo ""
echo "  Partição    : $PARTITION"
echo "  Filesystem  : exFAT"
echo "  Cluster size: ${CLUSTER_KB} KB"
echo "  Alinhamento : 4 MiB"
echo "  Label       : STORAGE"
echo ""
echo "Para benchmarkar: ./sd_bench.sh $(findmnt -n -o TARGET "$PARTITION" 2>/dev/null || echo '<ponto_de_montagem>')"

BINFILE_4_EOF
chmod +x "$BIN_DIR"/format_sd.sh
cat <<'BINFILE_5_EOF' > "$BIN_DIR"/merge-zxnet-pending-keys.sh
#!/usr/bin/env bash
set -euo pipefail

# Le chaves que o container web deixou prontas em pending-keys/ (ele mesmo
# nao pode escrever direto em authorized_keys -- sshd recusa via StrictModes
# qualquer authorized_keys gravavel por outro alem do dono) e funde de
# verdade, com o dono/permissao que o sshd exige.

PENDING_DIR="/var/zxnet/.ssh/pending-keys"
AUTH_KEYS="/var/zxnet/.ssh/authorized_keys"

[[ -d "$PENDING_DIR" ]] || exit 0

shopt -s nullglob
for f in "$PENDING_DIR"/*.pub; do
  line=$(cat "$f")
  key_part=$(printf '%s' "$line" | grep -oP 'ssh-\S+ \S+' || true)
  if [[ -n "$key_part" ]] && ! grep -qF "$key_part" "$AUTH_KEYS" 2>/dev/null; then
    printf '%s\n' "$line" >> "$AUTH_KEYS"
  fi
  rm -f "$f"
done

chown zxnet:users "$AUTH_KEYS"
chmod 600 "$AUTH_KEYS"

BINFILE_5_EOF
chmod +x "$BIN_DIR"/merge-zxnet-pending-keys.sh
cat <<'BINFILE_6_EOF' > "$BIN_DIR"/net_bench.sh
#!/usr/bin/env bash
# net_bench.sh -- testa a interface de rede ativa contra outros hosts
# conhecidos (descobertos via nmap na rede da rota padrao) e contra a
# internet (host "us" + speedtest). Pensado pra comparar adaptador A vs
# B: roda igual dos dois lados, compara os numeros no log.
#
# Uso:
#   ./net_bench.sh                # descobre a LAN (nmap -sn), testa quem tiver a porta 8422 aberta, + us + speedtest
#   ./net_bench.sh --host bag     # so testa um host extra (alias do ~/.ssh/config), alem da descoberta de LAN
#   ./net_bench.sh --no-lan       # pula a descoberta de LAN, so testa --host/us
#   ./net_bench.sh --no-wan       # pula o teste com "us" e o speedtest
#
# O que cada numero significa:
#   - hosts da LAN por cabo: mede so o adaptador do outro lado.
#   - hosts da LAN por wifi (o outro lado): mede o AP + o adaptador dele.
#     Pra comparar adaptador A vs B de forma justa, o lado fixo do teste
#     (voce) devia ficar por cabo -- o AP entra como constante nos dois
#     testes, nao como variavel.
#   - "us": atravessa seu uplink de internet inteiro (NAT, roteador,
#     provedor) -- numero de "quao rapido chega no meu servidor", nao de
#     rede local.
#
# Precisa de: nmap, iperf3 (dos DOIS lados), jq. SSH na porta 8422 (padrao
# da frota, ~/.ssh/config) com chave sem senha, login com o usuario normal
# de cada host -- sudo so pontualmente pra subir o servidor iperf3.
set -uo pipefail

SSH_PORT=8422
SSH_OPTS=(-p "$SSH_PORT" -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new -o BatchMode=yes)

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_DIR="$SCRIPT_DIR/../net-bench-logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/$(date +%Y%m%d-%H%M%S)-$(hostname -s).log"

DO_LAN=1
DO_WAN=1
EXTRA_HOSTS=()

while [[ $# -gt 0 ]]; do
  case "$1" in
    --host) EXTRA_HOSTS+=("$2"); shift 2 ;;
    --no-lan) DO_LAN=0; shift ;;
    --no-wan) DO_WAN=0; shift ;;
    *) echo "argumento desconhecido: $1" >&2; exit 1 ;;
  esac
done

log() { printf '%s\n' "$*" | tee -a "$LOG_FILE"; }

port_open() {
  timeout 2 bash -c "echo >/dev/tcp/$1/$2" 2>/dev/null
}

mbps() {
  awk -v b="$1" 'BEGIN{ if (b=="" || b=="null") print "n/d"; else printf "%.1f Mbps", b/1000000 }'
}

# Roda o pacote de testes contra $1 (ip ou alias do ~/.ssh/config).
# $2 (opcional) e so o rotulo pro log.
#
# A porta de dados do iperf3 (5201) costuma estar fechada no firewall de
# hosts de producao (o proprio "us" esta assim) -- abrir automaticamente
# seria repetir, em producao, o tipo de incidente que ja tivemos hoje
# mexendo em firewall alheio. Em vez disso: se 5201 nao responde direto,
# cai pra um tunel SSH local (porta 8422, que ja sabemos aberta) -- mais
# lento (soma overhead de criptografia), mas nao toca em firewall de
# ninguem. UDP so funciona no modo direto (tunel SSH e TCP).
run_iperf_suite() {
  local target="$1" label="${2:-$1}"
  log "--- iperf3: $label ($target) ---"

  ssh "${SSH_OPTS[@]}" "$target" \
    "sudo pkill -f '^iperf3 -s' >/dev/null 2>&1; sudo bash -c 'nohup iperf3 -s </dev/null >/tmp/iperf3-bench.log 2>&1 &'" \
    2>/dev/null
  sleep 1

  local client_host="$target" client_port=5201 via_tunnel=0 tunnel_pid=""
  if ! port_open "$target" 5201; then
    local local_port=$((20000 + RANDOM % 10000))
    ssh "${SSH_OPTS[@]}" -N -L "$local_port:localhost:5201" "$target" &
    tunnel_pid=$!
    sleep 1
    if ! port_open "localhost" "$local_port"; then
      log "  [aviso] nem direto nem por tunel SSH -- $target sem iperf3 acessivel, pulando"
      kill "$tunnel_pid" 2>/dev/null; wait "$tunnel_pid" 2>/dev/null
      return
    fi
    client_host="localhost"
    client_port="$local_port"
    via_tunnel=1
    log "  (5201 fechado direto -- medindo via tunel SSH, inclui overhead de criptografia)"
  fi

  local down up par udp_line udp_bps udp_jit udp_loss
  down=$(iperf3 -c "$client_host" -p "$client_port" -R -t 8 --json 2>/dev/null | jq -r '.end.sum_received.bits_per_second // empty')
  up=$(iperf3 -c "$client_host" -p "$client_port" -t 8 --json 2>/dev/null | jq -r '.end.sum_sent.bits_per_second // empty')
  par=$(iperf3 -c "$client_host" -p "$client_port" -P 4 -t 8 --json 2>/dev/null | jq -r '.end.sum_sent.bits_per_second // empty')

  log "  download (servidor->aqui):    $(mbps "$down")"
  log "  upload   (aqui->servidor):    $(mbps "$up")"
  log "  upload, 4 streams paralelos:  $(mbps "$par")"

  if [[ "$via_tunnel" -eq 0 ]]; then
    udp_line=$(iperf3 -c "$client_host" -u -b 200M -t 5 --json 2>/dev/null | jq -r '[.end.sum.bits_per_second, .end.sum.jitter_ms, .end.sum.lost_percent] | @tsv')
    if [[ -n "$udp_line" ]]; then
      read -r udp_bps udp_jit udp_loss <<< "$udp_line"
      log "  UDP (alvo 200Mbps):           $(mbps "$udp_bps"), jitter ${udp_jit}ms, perda ${udp_loss}%"
    fi
  else
    log "  UDP: pulado (nao da pra tunelar UDP por SSH -L)"
  fi

  [[ -n "$tunnel_pid" ]] && { kill "$tunnel_pid" 2>/dev/null; wait "$tunnel_pid" 2>/dev/null; }
  ssh "${SSH_OPTS[@]}" "$target" "sudo pkill -f '^iperf3 -s'" 2>/dev/null
}

IFACE=$(ip route show default | awk '{print $5; exit}')
MY_IP=$(ip -4 -o addr show "$IFACE" 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -1)

log "=== net_bench.sh $(date '+%Y-%m-%d %H:%M:%S') -- $(hostname -s) ==="
log "Interface: $IFACE   IP: $MY_IP"
log "Log: $LOG_FILE"
log ""

if [[ "$DO_LAN" -eq 1 ]]; then
  NET=$(ip -o -f inet addr show "$IFACE" 2>/dev/null | awk '{print $4}')
  log "=== Descobrindo hosts em $NET (nmap -sn) ==="
  mapfile -t found < <(nmap -sn "$NET" -oG - 2>/dev/null | awk '/Up$/{print $2}')
  log "Encontrados: ${found[*]:-nenhum}"
  log ""
  for ip in "${found[@]}"; do
    [[ "$ip" == "$MY_IP" ]] && continue
    printf '  %s porta %s: ' "$ip" "$SSH_PORT"
    if port_open "$ip" "$SSH_PORT"; then
      echo "aberta"
      run_iperf_suite "$ip"
    else
      echo "fechada, pulando"
    fi
    log ""
  done
fi

for h in "${EXTRA_HOSTS[@]}"; do
  run_iperf_suite "$h"
  log ""
done

if [[ "$DO_WAN" -eq 1 ]]; then
  log "=== Internet: teste com us (uplink real, atravessa NAT/provedor) ==="
  run_iperf_suite us us
  log ""

  if command -v speedtest-cli >/dev/null 2>&1; then
    log "=== speedtest-cli ==="
    speedtest-cli --simple 2>&1 | tee -a "$LOG_FILE"
  elif command -v speedtest >/dev/null 2>&1; then
    log "=== speedtest (Ookla) ==="
    speedtest --accept-license --accept-gdpr 2>&1 | grep -E "Download|Upload|Latency" | tee -a "$LOG_FILE"
  else
    log "speedtest-cli/speedtest nao instalado -- apt install speedtest-cli (pulando)"
  fi
  log ""
fi

log "=== Fim. Log salvo em $LOG_FILE ==="

BINFILE_6_EOF
chmod +x "$BIN_DIR"/net_bench.sh
cat <<'BINFILE_7_EOF' > "$BIN_DIR"/sd_bench.sh
#!/usr/bin/env bash
# Benchmark de armazenamento (SD cards, HDDs, SSDs, RAID)
# Uso: ./sd_bench.sh [diretório] ou usar diretório atual

TEST_DIR="${1:-.}"
cd "$TEST_DIR" || exit 1

echo "=== Testando: $(pwd) ==="
echo "Dispositivo: $(df -h . | tail -1 | awk '{print $1}')"
echo "Espaço livre: $(df -h . | tail -1 | awk '{print $4}')"
echo ""

# ==================== Testes Sequenciais Rápidos (dd) ====================
echo "### Escrita Sequencial (dd)"
echo -n "  512B blocks:  "
result=$(dd if=/dev/zero of=testfile bs=512 count=10k oflag=direct 2>&1 | grep -oE "[0-9]+\.?[0-9]* MB/s")
[[ -z "$result" ]] && result="$(dd if=/dev/zero of=testfile bs=512 count=10k 2>&1 | grep -oE "[0-9]+\.?[0-9]* MB/s") (buffered)"
echo "$result" ; rm -f testfile
echo -n "  4KB blocks:   " ; dd if=/dev/zero of=testfile bs=4k count=250k oflag=direct 2>&1 | grep -oE "[0-9]+\.?[0-9]* MB/s" ; rm -f testfile
echo -n "  512KB blocks: " ; dd if=/dev/zero of=testfile bs=512k count=3k oflag=direct 2>&1 | grep -oE "[0-9]+\.?[0-9]* MB/s" ; rm -f testfile
echo -n "  4MB blocks:   " ; dd if=/dev/zero of=testfile bs=4M count=500 oflag=direct 2>&1 | grep -oE "[0-9]+\.?[0-9]* MB/s" ; rm -f testfile
echo -n "  256MB blocks: " ; dd if=/dev/zero of=testfile bs=256M count=10 oflag=direct 2>&1 | grep -oE "[0-9]+\.?[0-9]* MB/s" ; rm -f testfile
echo ""

# ==================== hdparm (Leitura do dispositivo) ====================
echo "### Leitura do Dispositivo (hdparm)"
DEVICE=$(df -h . | tail -1 | awk '{print $1}')
if [[ $DEVICE == /dev/* ]]; then
    echo -n "  Teste 1: " ; sudo hdparm -t $DEVICE 2>&1 | tail -1 | cut -d'=' -f2
    echo -n "  Teste 2: " ; sudo hdparm -t $DEVICE 2>&1 | tail -1 | cut -d'=' -f2
else
    echo "  (não disponível para filesystem virtual)"
fi
echo ""

# ==================== fio: Testes Profissionais ====================
echo "### Escrita Aleatória 4K (simulação DB/Log)"
fio --name=random-write --ioengine=posixaio --rw=randwrite --bs=4k --size=1g --numjobs=1 --iodepth=1 --runtime=30 --time_based --end_fsync=1 2>/dev/null | grep -E "^ +write:" | grep -oE "BW=[0-9]+\.?[0-9]*[KMG]iB/s" | sed 's/BW=/  /'
rm -f random-write.0.0
echo ""

echo "### Throughput Sequencial (grandes arquivos)"
echo "  Write: " ; fio --name=write_throughput --size=2G --time_based --runtime=30s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=1M --iodepth=64 --rw=write --group_reporting=1 2>/dev/null | grep -E "^ +write:" | grep -oE "BW=[0-9]+\.?[0-9]*[KMG]iB/s" | sed 's/BW=/    /'
rm -f write_throughput.0.0

echo "  Read:  " ; fio --name=read_throughput --size=2G --time_based --runtime=30s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=1M --iodepth=64 --rw=read --group_reporting=1 2>/dev/null | grep -E "^ +read:" | grep -oE "BW=[0-9]+\.?[0-9]*[KMG]iB/s" | sed 's/BW=/    /'
rm -f read_throughput.0.0
echo ""

echo "### IOPS (operações/segundo - crítico para DB)"
echo "  Write: " ; fio --name=write_iops --size=2G --time_based --runtime=30s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=4K --iodepth=64 --rw=randwrite --group_reporting=1 2>/dev/null | grep -E "^ +write:" | grep -oE "IOPS=[0-9]+\.?[0-9]*k?" | sed 's/IOPS=/    /'
rm -f write_iops.0.0

echo "  Read:  " ; fio --name=read_iops --size=2G --time_based --runtime=30s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=4K --iodepth=64 --rw=randread --group_reporting=1 2>/dev/null | grep -E "^ +read:" | grep -oE "IOPS=[0-9]+\.?[0-9]*k?" | sed 's/IOPS=/    /'
rm -f read_iops.0.0

echo ""
echo "=== Teste concluído ==="

BINFILE_7_EOF
chmod +x "$BIN_DIR"/sd_bench.sh
cat <<'BINFILE_8_EOF' > "$BIN_DIR"/setup-thinkpad-l14gen2.sh
#!/bin/bash
#
# ============================================================================
#  setup-thinkpad-l14gen2.sh
#  Configuração completa do Lenovo ThinkPad L14 Gen 2 no Debian 13 (Trixie)
#
#  Assume:
#   - Sistema já instalado e bootando (raiz em ext4, /var e swap em LVM sobre LUKS)
#   - Mapper LUKS chamado "TP", VG "tp" com LVs "var" e "swap"
#   - SSD FIXO neste notebook (habilita recursos hardware-specific sem ressalvas)
#
#  Rode como usuário normal (ele chama sudo quando necessário).
#  Seções são independentes: pode comentar as que não quiser.
# ============================================================================

set -euo pipefail

# Garante /sbin no PATH (blkid, etc. ficam lá e somem do PATH de usuário comum)
export PATH="/usr/sbin:/sbin:$PATH"

log()  { echo -e "\n\033[1;32m==> $*\033[0m"; }
warn() { echo -e "\033[1;33m[!] $*\033[0m"; }

# ----------------------------------------------------------------------------
# 1. ENERGIA — TLP + thresholds de bateria (40/80 preserva a vida útil)
# ----------------------------------------------------------------------------
log "Instalando TLP e utilitários de energia"
sudo apt install -y tlp tlp-rdw acpi

# Remove power-profiles-daemon se existir (conflita com TLP)
sudo systemctl disable --now power-profiles-daemon 2>/dev/null || true
sudo apt purge -y power-profiles-daemon 2>/dev/null || true

# Aplica thresholds de carga no tlp.conf (idempotente: substitui se já existir)
sudo sed -i \
  -e 's/^#*START_CHARGE_THRESH_BAT0=.*/START_CHARGE_THRESH_BAT0=40/' \
  -e 's/^#*STOP_CHARGE_THRESH_BAT0=.*/STOP_CHARGE_THRESH_BAT0=80/' \
  /etc/tlp.conf
# Se as chaves não existiam no arquivo, adiciona
grep -q '^START_CHARGE_THRESH_BAT0=' /etc/tlp.conf || \
  echo 'START_CHARGE_THRESH_BAT0=40' | sudo tee -a /etc/tlp.conf >/dev/null
grep -q '^STOP_CHARGE_THRESH_BAT0=' /etc/tlp.conf || \
  echo 'STOP_CHARGE_THRESH_BAT0=80' | sudo tee -a /etc/tlp.conf >/dev/null

sudo systemctl enable --now tlp
sudo tlp start
log "Thresholds de bateria aplicados (confira com: sudo tlp-stat -b)"

# ----------------------------------------------------------------------------
# 2. thinkpad_acpi — controle de bateria, LEDs, fan, backlight
# ----------------------------------------------------------------------------
log "Garantindo carregamento do módulo thinkpad_acpi"
grep -qx 'thinkpad_acpi' /etc/modules || echo 'thinkpad_acpi' | sudo tee -a /etc/modules >/dev/null

# ----------------------------------------------------------------------------
# 3. thinkfan — controle de ventoinha (usa coretemp, detecção robusta por nome)
# ----------------------------------------------------------------------------
log "Instalando e configurando thinkfan"
sudo apt install -y thinkfan

# Detecta a plataforma do coretemp de forma estável (imune a reordenação de hwmon)
CORETEMP_PATH=$(readlink -f /sys/devices/platform/coretemp.0/hwmon 2>/dev/null || true)
if [ -n "$CORETEMP_PATH" ]; then
  sudo tee /etc/thinkfan.yaml >/dev/null <<'YAML'
# Controle de ventoinha por temperatura da CPU (coretemp / Package id 0)
# Formato name-based: imune a mudança de número do hwmon entre boots.
sensors:
  - hwmon: /sys/devices/platform/coretemp.0/hwmon
    name: coretemp
    indices: [1]

fans:
  - tpacpi: /proc/acpi/ibm/fan

# [nível_fan, temp_desce_abaixo, temp_sobe_acima]  (°C)
levels:
  - [0, 0, 55]
  - [1, 48, 60]
  - [2, 55, 65]
  - [3, 60, 70]
  - [7, 65, 32767]
YAML

  # Habilita controle manual da ventoinha no thinkpad_acpi (necessário para o
  # thinkfan conseguir escrever níveis em /proc/acpi/ibm/fan). Sem isso o
  # thinkfan roda mas os comandos de nível são ignorados pelo EC.
  echo 'options thinkpad_acpi fan_control=1' | sudo tee /etc/modprobe.d/thinkpad_acpi.conf >/dev/null
  sudo update-initramfs -u -k all

  sudo systemctl enable --now thinkfan
  log "thinkfan ativo usando coretemp (reinicie para o fan_control=1 valer 100%)"
else
  warn "coretemp não encontrado — pulei o thinkfan. Verifique com:"
  warn "  for f in /sys/class/hwmon/hwmon*/name; do echo \"\$f -> \$(cat \$f)\"; done"
fi

# ----------------------------------------------------------------------------
# 4. ÁUDIO — PipeWire (substitui PulseAudio) + firmware SOF
# ----------------------------------------------------------------------------
log "Instalando PipeWire e firmware de áudio"
sudo apt install -y pipewire pipewire-pulse pipewire-alsa wireplumber

# firmware-sof-signed é ESSENCIAL em plataformas Intel com DSP (Tiger Lake+).
# Sem ele, o kernel carrega os módulos normalmente mas o DSP falha silenciosamente
# ao inicializar (erro típico no dmesg: "firmware: failed to load intel/sof/sof-*.ri"),
# resultando em "no soundcards found" / apenas placa dummy disponível.
sudo apt install -y firmware-sof-signed alsa-firmware

# Recarrega o módulo para pegar o firmware recém-instalado sem precisar reiniciar
sudo modprobe -r snd_hda_intel 2>/dev/null || true
sudo modprobe snd_hda_intel 2>/dev/null || true

if aplay -l 2>/dev/null | grep -qi card; then
  log "Placa de áudio detectada com sucesso"
else
  warn "Áudio ainda não detectado — um reboot deve resolver (firmware SOF só é lido no boot em alguns casos)"
fi
# Bluetooth Intel funciona nativo (firmware já incluso) — nada a fazer aqui.

# ----------------------------------------------------------------------------
# 5. FIRMWARE — atualizações via LVFS (fwupd)
# ----------------------------------------------------------------------------
log "Verificando atualizações de firmware (fwupd)"
sudo apt install -y fwupd
sudo fwupdmgr refresh --force || true
sudo fwupdmgr get-updates || true
warn "Rode 'sudo fwupdmgr update' manualmente se houver atualizações listadas acima."

# ----------------------------------------------------------------------------
# 6. TRACKPOINT — sensibilidade/velocidade persistente via udev
# ----------------------------------------------------------------------------
log "Criando regra udev do TrackPoint"
sudo tee /etc/udev/rules.d/10-trackpoint.rules >/dev/null <<'RULE'
ACTION=="add", SUBSYSTEM=="serio", DRIVERS=="psmouse", ATTR{sensitivity}="200", ATTR{speed}="100"
RULE
sudo udevadm control --reload-rules
log "TrackPoint configurado (sensitivity=200, speed=100 — ajuste no arquivo se quiser)"

# ----------------------------------------------------------------------------
# 7. FINGERPRINT — leitor de digital (opcional, interativo)
# ----------------------------------------------------------------------------
log "Instalando suporte a leitor de digital"
sudo apt install -y fprintd libpam-fprintd
echo
read -rp "Cadastrar digitais agora? [s/N] " RESP
if [[ "${RESP,,}" == "s" ]]; then
  for FINGER in right-index-finger right-middle-finger left-index-finger; do
    read -rp "Cadastrar $FINGER? [s/N] " R2
    [[ "${R2,,}" == "s" ]] && fprintd-enroll -f "$FINGER" || true
  done
  warn "Para usar digital no login/sudo: sudo pam-auth-update (marque 'Fingerprint authentication')"
else
  warn "Pulado. Depois use: fprintd-enroll -f right-index-finger (e outros dedos)"
fi

# ----------------------------------------------------------------------------
# 8. HIBERNAÇÃO — resume a partir do swap dentro do LUKS+LVM
# ----------------------------------------------------------------------------
log "Configurando hibernação (swap em LUKS+LVM)"

SWAP_DEV=/dev/tp/swap
if [ -e "$SWAP_DEV" ]; then
  RESUME_UUID=$(blkid -s UUID -o value "$SWAP_DEV")
  if [ -n "$RESUME_UUID" ]; then
    # a) grava RESUME para o initramfs
    echo "RESUME=UUID=$RESUME_UUID" | sudo tee /etc/initramfs-tools/conf.d/resume >/dev/null

    # b) força o LUKS a abrir no initramfs (senão o swap não existe no resume)
    if ! grep -q 'initramfs' /etc/crypttab; then
      sudo sed -i 's/luks,discard/luks,discard,initramfs/' /etc/crypttab
    fi

    # c) adiciona resume= ao GRUB_CMDLINE_LINUX_DEFAULT (sem duplicar)
    if ! grep -q "resume=UUID=$RESUME_UUID" /etc/default/grub; then
      sudo sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"|GRUB_CMDLINE_LINUX_DEFAULT=\"\1 resume=UUID=$RESUME_UUID\"|" /etc/default/grub
      # limpa espaço extra caso o valor estivesse vazio
      sudo sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=" |GRUB_CMDLINE_LINUX_DEFAULT="|' /etc/default/grub
    fi

    # d) regenera
    sudo update-initramfs -u -k all
    sudo update-grub
    log "Hibernação configurada. Teste com: sudo systemctl hibernate"
    warn "No próximo boot a senha do LUKS será pedida mais cedo (estágio initramfs)."
  else
    warn "Não consegui obter o UUID de $SWAP_DEV — hibernação NÃO configurada."
  fi
else
  warn "$SWAP_DEV não existe — ajuste SWAP_DEV no script se seu VG/LV tiver outro nome."
fi

# ----------------------------------------------------------------------------
# CONCLUSÃO
# ----------------------------------------------------------------------------
log "Configuração concluída!"
echo "Recomendado reiniciar para validar hibernação e ordem de boot."
echo
echo "Comandos úteis de verificação:"
echo "  sudo tlp-stat -b           # thresholds de bateria"
echo "  sudo thinkfan -n           # testar thinkfan em foreground (Ctrl+C sai)"
echo "  fprintd-list \$USER          # digitais cadastradas"
echo "  sudo systemctl hibernate   # testar hibernação"

BINFILE_8_EOF
chmod +x "$BIN_DIR"/setup-thinkpad-l14gen2.sh
cat <<'BINFILE_9_EOF' > "$BIN_DIR"/srv_disk_test.sh
#!/usr/bin/env bash
#set -e

if [[ $1 == "-d" || $# -eq 0 ]]; then
    # hdparm -t $(df -h . | tail -1 | awk '{print $1}') | tail -1 | cut -d'=' -f2
    # hdparm -t $(df -h . | tail -1 | awk '{print $1}') | tail -1 | cut -d'=' -f2

    # echo -e "\nconv=fdatasync"
    # dd if=/dev/zero of=output conv=fdatasync bs=512 count=4000k; rm -f output
    # dd if=/dev/zero of=output conv=fdatasync bs=4k count=500k; rm -f output
    # dd if=/dev/zero of=output conv=fdatasync bs=512k count=4k; rm -f output
    # dd if=/dev/zero of=output conv=fdatasync bs=4M count=500; rm -f output
    # dd if=/dev/zero of=output conv=fdatasync bs=256M count=10; rm -f output

    echo -e "\noflag=direct"
    dd if=/dev/zero of=testfile bs=512 count=10k oflag=direct 2>&1 | grep --color=always -oE " [0-9]+\.?[0-9]+ MB/s"; rm -f testfile
    dd if=/dev/zero of=testfile bs=4k count=250k oflag=direct 2>&1 | grep --color=always -oE " [0-9]+\.?[0-9]+ MB/s"; rm -f testfile
    dd if=/dev/zero of=testfile bs=512k count=3k oflag=direct 2>&1 | grep --color=always -oE " [0-9]+\.?[0-9]+ MB/s"; rm -f testfile
    dd if=/dev/zero of=testfile bs=4M count=500 oflag=direct 2>&1 | grep --color=always -oE " [0-9]+\.?[0-9]+ MB/s"; rm -f testfile
    dd if=/dev/zero of=testfile bs=256M count=10 oflag=direct 2>&1 | grep --color=always -oE " [0-9]+\.?[0-9]+ MB/s"; rm -f testfile

    hdparm -t $(df -h . | tail -1 | awk '{print $1}') | tail -1 | cut -d'=' -f2
    hdparm -t $(df -h . | tail -1 | awk '{print $1}') | tail -1 | cut -d'=' -f2


    echo -e "\n- Random"
    fio --name=random-write --ioengine=posixaio --rw=randwrite --bs=4k --size=4g --numjobs=1 --iodepth=1 --runtime=60 --time_based --end_fsync=1  | grep "WRITE:" | grep --color=always -oE "=[0-9]+\.?[0-9]+MiB/s "
    rm random-write.0.0

    echo -e "\n- Write"
    fio --name=write_throughput --size=5G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=1M --iodepth=64 --rw=write --group_reporting=1 | grep "WRITE:" | grep --color=always -oE "=[0-9]+\.?[0-9]+MiB/s "
    rm write_throughput.0.0
    fio --name=write_iops --size=5G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=4K --iodepth=64 --rw=randwrite --group_reporting=1 | grep "WRITE:" | grep --color=always -oE "=[0-9]+\.?[0-9]+MiB/s "
    rm write_iops.0.0

    echo -e "\n- Read"
    fio --name=read_throughput --size=5G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=1M --iodepth=64 --rw=read --group_reporting=1 | grep "READ:" | grep --color=always -oE "=[0-9]+\.?[0-9]+MiB/s "
    rm read_throughput.0.0
    fio --name=read_iops --size=5G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --verify=0 --bs=4K --iodepth=64 --rw=randread --group_reporting=1 | grep "READ:" | grep --color=always -oE "=[0-9]+\.?[0-9]+MiB/s "
    rm read_iops.0.0
fi

if [[ $1 == "-p" || $# -eq 0 ]]; then
    sysbench cpu --threads=1 run | grep --color=always "per second:"
    sysbench cpu --threads=2 run | grep --color=always "per second:"

    sysbench cpu --threads=6 run | grep --color=always "per second:"
    sysbench cpu --threads=12 run | grep --color=always "per second:"

    echo -e "Memória"
    sysbench memory --threads=1 run | grep "MiB/sec"
    sysbench memory --threads=1 --memory-block-size=1M --memory-total-size=10G run | grep "MiB/sec"
    sysbench memory --threads=2 run | grep "MiB/sec"
    sysbench memory --threads=2 --memory-block-size=1M --memory-total-size=10G run | grep "MiB/sec"

    sysbench memory --threads=6 run | grep "MiB/sec"
    sysbench memory --threads=6 --memory-block-size=1M --memory-total-size=10G run | grep "MiB/sec"
fi

# for i in us ny mo nyc use usc; do echo -e "\n\n$i\n" ; ssh $i  | grep "MiB/sec"; done

# for i in us ny mo nyc use usc; do echo -e "\n\n$i\n" ; ssh $i wget http://www.cs.virginia.edu/stream/FTP/Code/stream.c ; gcc -O stream.c -o stream ; ./stream; done

# fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=random_read_write.fio --bs=4k --iodepth=64 --size=250M --readwrite=randrw --rwmixread=80


exit 0

TEST_DIR=/mnt/disks/mnt_dir/fiotest
sudo mkdir -p $TEST_DIR



BINFILE_9_EOF
chmod +x "$BIN_DIR"/srv_disk_test.sh
  fi

  # Home: mesma logica -- symlink se o Syncthing local ja sincronizou,
  # senao conteudo atual servido pelo /init.
  # Mesma correcao do bloco de bin, e foi este que doeu: no d7 (que nao tem
  # nem vai ter Syncthing) o host terminou SEM authorized_keys, e portanto
  # inacessivel com as chaves atuais. O diretorio existia vazio, o find
  # nao achou arquivo nenhum, e o else que grava o conteudo servido nunca
  # rodou.
  #
  # Regra: o host tem que sair utilizavel em QUALQUER estado do Syncthing --
  # sem ele, com ele vazio, ou sincronizado. Link so' quando ha o que linkar.
  if [[ -d $SYNC_HOME ]] && [[ -n "$(find "$SYNC_HOME" -type f -print -quit 2>/dev/null)" ]]; then
    for i in $(find "$SYNC_HOME" -type f); do
      rm "$HOME_USER""${i#$SYNC_HOME}" &> /dev/null
      ln -s "$i" "$HOME_USER""${i#$SYNC_HOME}"
      chown -h $USER: "$HOME_USER""${i#$SYNC_HOME}"
    done
  else
    rm $HOME_USER/.bashrc &> /dev/null
    cat <<'EOF' > $HOME_USER/.bashrc
case $- in
    *i*) ;;
      *) return;;
esac			# If not running interactively, don't do anything

HISTSIZE=10000
HISTFILESIZE=20000
HISTCONTROL=ignoreboth
HISTIGNORE='l:ll:pwd:htop:history:fg'
HISTTIMEFORMAT='%F %T '

PROMPT_COMMAND='history -a'

shopt -s histappend
shopt -s cmdhist
shopt -s checkwinsize

[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi
case "$TERM" in
    xterm-color|*-256color) color_prompt=yes;;
esac
force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
        color_prompt=yes
    else
        color_prompt=
    fi
fi
if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
case "$TERM" in
    xterm*|rxvt*) PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" ;;
    *) ;;
esac

if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

if [ -d "$HOME/.local/bin" ] ; then
  case ":$PATH:" in
    *":$HOME/.local/bin:"*) : ;; # already there
    *) PATH="$HOME/.local/bin:$PATH" ;;
  esac
fi

alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

alias grep='grep --color=auto'
alias ll='ls -lAhF'
alias la='ls -A'
alias l='ls -lh'

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

complete -C /usr/bin/terraform terraform
alias ic="ibmcloud"


EOF
    rm $HOME_USER/.bash_aliases &> /dev/null
    cat <<'EOF' > $HOME_USER/.bash_aliases
export EDITOR="nano"
export DATASTORE_TYPE=kubernetes

alias ll='ls -lah'
alias la='ls -A'
alias l='ls -lh'

alias llsbkl='lsblk -S -o NAME,TRAN,MODEL,SERIAL,SIZE'

alias supersync='sudo rsync -az -e "ssh -l rcaldas -i /var/rcaldas/.ssh/id_ed25519" --rsync-path="sudo rsync" --numeric-ids --progress'

alias smtp-logs="ssh us 'docker logs -f mailu-smtp-1 --since 1h'"
#alias smtp-logs="ssh us 'docker logs -f mailu-smtp-1 --since 1h' | grep -v 'connect from localhost'"

alias volume='mate-volume-control-status-icon &> /dev/null &'
alias som='pulseaudio -k && alsa force-reload'

which kubectl >/dev/null && source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k

alias kubesystem='watch kubectl -n kube-system get pod -o wide'

alias duse='for i in `sudo ls -A`; do sudo du -hs $i; done'

alias tey="docker compose down --remove-orphans && docker compose up -d --build && docker compose logs -f"

alias aws='docker run --rm -it -v ~/.aws:/root/.aws -v $(pwd):/aws amazon/aws-cli'

alias random="cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1"

alias vncon="sudo x11vnc -rfbauth /var/rcaldas/.vnc_pwd -display :0 -nevershared -forever -auth /var/run/lightdm/root/:0"
alias vncon2="x11vnc -rfbauth /var/rcaldas/.vnc_pwd -create -env FD_PROG=/usr/bin/startxfce4 -nevershared -forever -rfbport 5901"

alias nvidia="sudo xrandr --setprovideroutputsource NVIDIA-G0 modesetting && sudo xrandr --auto"

#alias alku='for i in fl nj atl ; do echo $i; ssh -t $i '
alias aldeb='for i in us bg hm p25; do echo $i; ssh -t $i '

alias attall='for i in us bag tp len m2 r64 d7; do echo -e "\n:::\n:::\n:::\n\nHost $i\n\n:::\n:::\n:::\n" && ssh $i "sudo apt update > /dev/null && sudo apt upgrade -y && sudo apt full-upgrade -y && sudo apt autoremove -y && sudo apt clean"; done'
alias attdeb='sudo apt update >/dev/null && sudo apt upgrade -y && sudo apt full-upgrade -y && sudo apt autoremove -y && sudo apt clean'

alias dc='docker compose'

alias odtgrep='for i in /var/rcaldas/sync/concurso/* ; do echo -e "\n\t----- ##### $i ##### -----:\n" ; odt2txt "$i" | grep '

alias brilho='xrandr --output $(xrandr | grep " connected" | cut -d" " -f1 | head -n1) --brightness'


# ============================================================================
# ThinkPad L14 Gen 2 — aliases de energia e bateria
# ============================================================================

# --- Bateria: status e thresholds -------------------------------------------

# Status completo da bateria (fonte de verdade: sysfs via tlp-stat, não upower)
alias bat='sudo tlp-stat -b'

# Só o essencial: %, status, thresholds (mais rápido de ler)
alias bat-status='cat /sys/class/power_supply/BAT0/capacity; \
  echo "Status: $(cat /sys/class/power_supply/BAT0/status)"; \
  echo "Thresholds: $(cat /sys/class/power_supply/BAT0/charge_control_start_threshold)% - $(cat /sys/class/power_supply/BAT0/charge_control_end_threshold)%"'

# --- Modos de carga ----------------------------------------------------------

# Carrega até 100% uma vez (viagem, uso fora de casa) — volta ao normal depois
alias carregar-tudo='sudo tlp fullcharge BAT0 && echo "Carregando até 100%. Volta ao normal (40/80) após desconectar/religar."'

# Volta ao modo economia (40/80) manualmente, se quiser forçar antes da hora
alias carregar-normal='sudo tlp setcharge 40 80 BAT0 && echo "Thresholds voltaram para 40%-80%"'

# Ajusta o teto pra 90% (meio-termo: mais autonomia que 80%, menos desgaste que 100%)
alias carregar-90='sudo tlp setcharge 40 90 BAT0 && echo "Teto ajustado para 90%"'

# --- TLP geral ----------------------------------------------------------------

alias tlp-on='sudo tlp start'
alias tlp-check='sudo tlp-stat -s'          # status geral do TLP (modo AC/BAT, etc)

# --- Ventoinha (thinkfan) -----------------------------------------------------
alias fan-status='systemctl status thinkfan --no-pager | head -8; cat /proc/acpi/ibm/fan | head -3'

# Testa o thinkfan em foreground, mostrando temperatura/nível em tempo real (Ctrl+C sai)
alias fan-test='sudo thinkfan -n -b 0'

# Temperatura atual da CPU (rápido, sem abrir mais nada)
alias cputemp='cat /sys/devices/platform/coretemp.0/hwmon/hwmon*/temp1_input | awk "{print \$1/1000\"°C\"}"'

# --- Firmware -------------------------------------------------------------

alias fw-check='sudo fwupdmgr refresh --force && sudo fwupdmgr get-updates'
alias fw-update='sudo fwupdmgr update'

# --- Hibernação / suspensão ----------------------------------------------------

alias hibernar='sudo systemctl hibernate'
alias suspender='sudo systemctl suspend'

# --- Resumo completo ----------------------------------------------------------

# Visão geral: bateria, thresholds, TLP e temperatura, tudo de uma vez
alias energia='echo "=== Bateria ===" && \
  echo "Carga:   $(cat /sys/class/power_supply/BAT0/capacity)%" && \
  echo "Status:  $(cat /sys/class/power_supply/BAT0/status)" && \
  echo "Limites: $(cat /sys/class/power_supply/BAT0/charge_control_start_threshold)% - $(cat /sys/class/power_supply/BAT0/charge_control_end_threshold)%" && \
  echo "Ciclos:  $(cat /sys/class/power_supply/BAT0/cycle_count 2>/dev/null || echo "N/D")" && \
  echo "" && \
  echo "=== TLP ===" && \
  sudo tlp-stat -s | grep -E "^Mode|^State" && \
  echo "" && \
  echo "=== Temperatura CPU ===" && \
  awk "{print \$1/1000\"°C\"}" /sys/devices/platform/coretemp.0/hwmon/hwmon*/temp1_input'

EOF
    rm $HOME_USER/.ssh/authorized_keys &> /dev/null
    cat <<'EOF' > $HOME_USER/.ssh/authorized_keys

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPGXdbGsZd/DzjR/nu0zbouKbcQdKauA05DpLNGIgmhS rcaldas@tp
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJu8MW2BUqweZZSpZSX4CZO7yIypNBaikz8meDTG6pl4 rcaldas@bag
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIl76z5ByO9duilEprSkF59ByXo9+xDy356Ikf7fTAMB N20U

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKhRZc0pqm0El1yTZLCG8/uUc3n5l4+cZfxvTohCrvvs rcaldas@P25W
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOT+SXjLcSNiV8QKgSKMIuaYflt5kQD80xtgr303y4ni rcaldas@len
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPJGMf4cFU2ORrtz3QD6VFRBImoqNiCgWzJwWvO4fvR6 rcaldas@m2
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPvMnVufCCPxTYExnEQHj4voQeNP4lm7Ncozhe6dE5p1 rcaldas@home

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPT+3bve0HkTXMfd78UHDmoAN1zOLSi6cFC3/mqNaR1z rcaldas@n9

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUWDfpnLwszGkDGkasRkH6ZegzByVWuAGr/aY8RbVGF rcaldas@us

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ6Sh5+Grbh708nE7vZmlER6UU67yiXsO3NYXeGBjfmm rcaldas@m2

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFArnk8mCotTSLCR/NaheqygTAt1Xa1y+Zd5MM1/KbPo robca@N-01018930
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDWn6Rvu7ZKHmh1fSFGA12AJV3I1Lt9fAjCoDU+vfAXJ S22
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdkOiDEuCzVWjdO7A8q4k386RQbgj6E4xRB888He8SC N12

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBCEb9Fn7QDDAows9mCnz2MHJYilPmkGGI7LzTcgKFJr bndes\robca@N-00954764
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKZNqe/xQr59cm8NQhqUKNVbldA9ujOHgFmZsY9Q1q5F backup-runner@bag
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP2wiEbX3zkP0XWOlyUNkmLU8g7E9v1r8esW8ixJn1Ig rcaldas@r64

EOF
    rm $HOME_USER/.ssh/config &> /dev/null
    cat <<'EOF' > $HOME_USER/.ssh/config
Host *
	ServerAliveInterval 300
	ServerAliveCountMax 5
	ExitOnForwardFailure yes



Host us
	HostName us.rcaldas.com
	Port 8422

Host bag
	HostName bag.rcaldas.com
	Port 8422
Host bagt
	HostName us.rcaldas.com
	Port 7701
Host bagl
	HostName 192.168.1.12
	Port 8422

Host tp
	HostName tp.rcaldas.com
	Port 8422
Host tpt
	HostName us.rcaldas.com
	Port 7702
Host tpl
	HostName 192.168.1.26
	Port 8422

Host r64
	HostName r64.rcaldas.com
	Port 8422
Host r64t
	HostName us.rcaldas.com
	Port 7705
Host r64l
	HostName 192.168.1.38
	Port 8422

Host len
	HostName len.rcaldas.com
	Port 8422
Host lent
	HostName us.rcaldas.com
	Port 7703
Host lenl
	HostName 192.168.1.4
	Port 8422

Host d7l
	HostName 192.168.1.31
	Port 8422
Host d7t
	HostName us.rcaldas.com
	Port 7707
Host d7
	HostName d7.rcaldas.com
	Port 8422

Host m2
	HostName m2.rcaldas.com
	Port 8422
Host m2t
	HostName us.rcaldas.com
	Port 7782

Host p25
	HostName us.rcaldas.com
	Port 7784
Host n9
	HostName us.rcaldas.com
	Port 7789

Host lev
	HostName lev.rcaldas.com
	Port 8422
Host levt
	HostName us.rcaldas.com
	Port 7709

EOF
  fi

  for file in $(ls -Ad $HOME_USER/.??*); do
    chown -Rh $USER: $file
  done

  rm /root/.bashrc &> /dev/null
  cp $HOME_USER/.bashrc /root/.bashrc
  cp $HOME_USER/.ssh/config /root/.ssh/

  [[ -f $HOME_USER/.gitconfig ]] || \
      su - $USER -c "cat <<EOF > $HOME_USER/.gitconfig
[user]
email = $HOSTNAME@$DOMAIN
name = $NAME_USER
[cola]
spellcheck = false
[pull]
rebase = false
EOF"

  sed -i "/#*$USER\t/d" /etc/sudoers
  echo -e "$USER\tALL=(ALL)\tNOPASSWD:ALL" >> /etc/sudoers
}

function set_tune2fs(){
  echo tune2fs
  for i in / /var /var/log /home; do
    PART=$(df $i | grep $i$ | awk '{ print $1 }')
    [[ -n $PART ]] && {
      sudo tune2fs -c 2 $PART &> /dev/null
    }
  done
}

function set_syncthing(){
  echo Syncthing
  sudo mkdir -p /etc/apt/keyrings
  sudo curl -L -o /etc/apt/keyrings/syncthing-archive-keyring.gpg https://syncthing.net/release-key.gpg
  echo "deb [signed-by=/etc/apt/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable" | sudo tee /etc/apt/sources.list.d/syncthing.list
  printf "Package: *\nPin: origin apt.syncthing.net\nPin-Priority: 990\n" | sudo tee /etc/apt/preferences.d/syncthing.pref

  echo "fs.inotify.max_user_watches=204800" | sudo tee /etc/sysctl.d/syncthing.conf > /dev/null
  sysctl --system > /dev/null
  package_installer "syncthing"
}

function set_docker(){
  echo Docker
  apt-get -qq remove docker docker-engine docker.io containerd runc &> /dev/null
  install -m 0755 -d /etc/apt/keyrings
  curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --yes --dearmor -o /etc/apt/keyrings/docker.gpg
  chmod a+r /etc/apt/keyrings/docker.gpg
  echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
  package_installer "docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"

  cat > /etc/sysctl.d/docker.conf <<'EOF'
vm.max_map_count=262144

fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512
EOF
  sysctl --system > /dev/null

  systemctl enable docker &> /dev/null
  usermod -aG docker "$USER" > /dev/null
}

### Desktop tasks
function set_swappiness(){
  echo swappiness
  echo "vm.swappiness=10" > /etc/sysctl.d/swappiness.conf
  sysctl --system > /dev/null
}

function set_lightdm(){
  echo lightdm
  if dpkg -s lightdm &> /dev/null; then
    if [ -f /usr/share/lightdm/lightdm.conf.d/01_debian.conf ]; then
      cat <<EOF > /usr/share/lightdm/lightdm.conf.d/01_debian.conf
[Seat:*]
greeter-session=lightdm-greeter
greeter-hide-users=false
session-wrapper=/etc/X11/Xsession
allow-user-switching=true
EOF
    else
      if [ -f /etc/lightdm/lightdm.conf ]; then
        sed -i '/^#*greeter-hide-users/c\greeter-hide-users=false' /etc/lightdm/lightdm.conf
        sed -i '/^#*allow-user-switching/c\allow-user-switching=true' /etc/lightdm/lightdm.conf
      else
        echo -e "No lightdm configuration files found!\n"
      fi
    fi
  fi

  if [ -f /usr/share/lightdm/lightdm-gtk-greeter.conf.d/01_debian.conf ]; then
    curl -fLksm10 -o /usr/share/images/wallpaper.jpg $WALLPAPER
    sed -i '/background=/c\background=/usr/share/images/wallpaper.jpg' /usr/share/lightdm/lightdm-gtk-greeter.conf.d/01_debian.conf
  fi
}

function firefox(){
  echo Firefox
  su - $USER -c "mkdir -p $HOME_USER/.local/share/{applications,icons} \
                          $HOME_USER/.local/bin"

  # A Mozilla NAO publica tarball oficial pra ARM -- so' x86_64. Em
  # armhf/arm64 o unico caminho e' o firefox-esr da distro, que ja traz o
  # proprio .desktop e o proprio binario em /usr/bin.
  #
  # Repare que isso inverte o resto da funcao: em amd64 o firefox-esr e'
  # REMOVIDO de proposito, justamente pra dar lugar ao tarball oficial (mais
  # novo que o ESR). Em ARM ele e' o que queremos manter -- por isso o
  # retorno antecipado, antes do remove.
  if [ "$DPKG_ARCH" != "amd64" ]; then
    DEBIAN_FRONTEND=noninteractive apt-get -qq install firefox-esr > /dev/null 2>&1 \
      || { echo "  AVISO: firefox-esr indisponivel para $DPKG_ARCH -- seguindo sem navegador"; return 0; }
    update-alternatives --install /usr/bin/x-www-browser x-www-browser /usr/bin/firefox-esr 10 > /dev/null 2>&1 || true
    update-alternatives --set x-www-browser /usr/bin/firefox-esr > /dev/null 2>&1 || true
    echo "  firefox-esr da distro (sem build ARM oficial da Mozilla)"
    return 0
  fi

  dpkg -s firefox-esr &> /dev/null && \
    apt-get remove -y --no-install-recommends firefox-esr > /dev/null

  if [[ ! -d $HOME_USER/.local/share/firefox ]]; then
    curl -Ls $FIREFOX_URL -o /tmp/firefox.tar.xz
    su - $USER -c "tar -xJf /tmp/firefox.tar.xz -C $HOME_USER/.local/share/"
    rm /tmp/firefox.tar.xz
  fi

  chmod a+x $HOME_USER $HOME_USER/.local $HOME_USER/.local/share \
            $HOME_USER/.local/share/firefox

  ln -fs $HOME_USER/.local/share/firefox/firefox-bin $BIN_DIR/firefox

  update-alternatives --install /usr/bin/x-www-browser x-www-browser "$BIN_DIR"/firefox 10 > /dev/null
  update-alternatives --set x-www-browser "$BIN_DIR"/firefox > /dev/null
  update-alternatives --install /usr/bin/gnome-www-browser gnome-www-browser "$BIN_DIR"/firefox 10 > /dev/null
  update-alternatives --set gnome-www-browser "$BIN_DIR"/firefox > /dev/null

  cat <<EOF > /usr/share/applications/firefox.desktop
[Desktop Entry]
Name=Firefox
Comment=Browse the World Wide Web
GenericName=Web Browser
X-GNOME-FullName=Firefox Web Browser
Exec=$HOME_USER/.local/share/firefox/firefox-bin %u
Terminal=false
X-MultipleArgs=false
Type=Application
Icon=firefox
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;
StartupWMClass=Firefox
StartupNotify=true
EOF
  echo "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" \
    | base64 --decode > /usr/share/icons/firefox.png
}

function set_vscode(){
  echo vscode
  # Se o VSCode ja foi instalado pelo pacote .deb oficial da Microsoft, ele
  # mesmo gerencia /etc/apt/sources.list.d/vscode.sources com sua propria
  # keyring. Escrever um vscode.list nosso por cima disso define a mesma
  # fonte duas vezes com Signed-By diferente, e o apt recusa ler a lista de
  # fontes inteira ate isso ser resolvido manualmente -- ja aconteceu.
  if [[ -f /etc/apt/sources.list.d/vscode.sources || -f /etc/apt/sources.list.d/vscode.list ]]; then
    package_installer "code"
    return
  fi
  wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
  install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
  sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
  rm -f packages.microsoft.gpg
  package_installer "code"
}


echo ":: INIT - RCALDAS ::"

ask_user
asks
echo -e "\n\t>> Working, please wait... <<\n"


if [[ -n $NEWHOSTNAME ]]; then
  set_hostname
fi

set_dns
set_timezone
set_packages

if [ "$CHANGESSH" == "n" ] || [ "$CHANGESSH" == "N" ]; then
  :
else
  set_ssh
fi

set_fail2ban
ensure_root_key
set_local_mail
set_user
# Depois do set_user: precisa do $HOME_USER/.ssh ja criado.
set_backup_access
set_tune2fs

if [ "$INSTSYNC" == "y" ] || [ "$INSTSYNC" == "Y" ]; then
  set_syncthing
fi

if [ "$INSTDOCKER" == "y" ] || [ "$INSTDOCKER" == "Y" ]; then
  set_docker
fi

if [ "$ISDESKTOP" == "y" ] || [ "$ISDESKTOP" == "Y" ]; then
  set_swappiness
  set_lightdm
  firefox
  set_vscode
  package_installer "$desktop_apps"
fi

apt-get -qq upgrade > /dev/null
apt-get -qq autoremove > /dev/null
apt-get -qq clean

fastfetch

echo -e "\n\t>> Ativando monitoramento/DDNS... <<\n"
curl -fsSL "https://web.rcaldas.com/install" | bash

echo -e "\n\t>> Done! <<\n"
exit 0
