#!/bin/bash
# RNRemote - Instalação / Atualização do agente (CentOS 7)
# Uso: sudo bash install-centos7.sh
#
# CentOS 7 encerrou todo suporte oficial em 30/06/2024 (inclusive o ELS pago da
# Red Hat). Chrome/Chromium atuais exigem glibc >= 2.18 e o CentOS 7 trava em
# glibc 2.17 — não existe build de Chromium atualizada que rode nele. Pra
# viabilizar a aba "Web Browser" (navegador remoto headless) nessa máquina, o
# próprio agent.py detecta isso automaticamente e baixa o Firefox oficial como
# alternativa: ao contrário do Chromium, o Firefox atual continua compatível
# com glibc 2.17 no motor principal mesmo nas versões mais recentes — ou seja,
# roda com todos os patches de segurança em dia, sem precisar aceitar nenhuma
# build antiga/desatualizada. Esse script não baixa navegador nenhum — isso é
# 100% responsabilidade do agente, ver `ensure_browser()` em agent.py.

set -e

BOLD="\033[1m"; GREEN="\033[32m"; RED="\033[31m"; CYAN="\033[36m"; YELLOW="\033[33m"; DIM="\033[2m"; RESET="\033[0m"
ok()   { echo -e "  ${GREEN}✔${RESET}  $1"; }
err()  { echo -e "  ${RED}✘${RESET}  $1"; exit 1; }
info() { echo -e "  ${DIM}→${RESET}  $1"; }
warn() { echo -e "  ${YELLOW}!${RESET}  $1"; }

echo -e "\n${CYAN}${BOLD}╔══════════════════════════════════════════╗"
echo -e "║  RNRemote — Instalação (CentOS 7)        ║"
echo -e "╚══════════════════════════════════════════╝${RESET}\n"

# ── Root ──────────────────────────────────────────────────────────────────────
[ "$EUID" -ne 0 ] && err "Execute como root: sudo bash install-centos7.sh"

SERVICE="rnremote-agent"
INSTALL_DIR="/opt/rnremote"
CONF_DIR="/etc/rnremote"
SVC_FILE="/etc/systemd/system/${SERVICE}.service"
PANEL_URL="https://rnremote.joaoneto.tec.br"

# ── Confere que é CentOS 7 mesmo ──────────────────────────────────────────────
if [ -f /etc/os-release ]; then
    . /etc/os-release
    if [ "${ID}" != "centos" ] || [ "${VERSION_ID%%.*}" != "7" ]; then
        warn "Este script é específico pra CentOS 7 (detectei: ${PRETTY_NAME:-desconhecido})."
        warn "Pra CentOS Stream 9 / RHEL 9 use install-centos.sh."
        read -rp "  Continuar mesmo assim? [s/N] " CONT
        [ "$CONT" != "s" ] && [ "$CONT" != "S" ] && err "Instalação cancelada."
    fi
else
    warn "Não consegui identificar a distro (/etc/os-release ausente) — seguindo mesmo assim."
fi

# ── Repos YUM ──────────────────────────────────────────────────────────────────
# 1) CentOS 7 encerrou todo suporte oficial em 30/06/2024 e o
#    mirrorlist.centos.org (usado por padrão pelos repos base/extras/updates) foi
#    desligado de vez — qualquer `yum install` novo falha com "Could not resolve
#    host: mirrorlist.centos.org" nessa altura, em QUALQUER máquina, não é um
#    problema local. Fix padrão: redirecionar os repos pro arquivo histórico
#    (vault.centos.org), que a Red Hat mantém justamente pra releases fora de
#    suporte. Só mexe nos arquivos se detectar o sintoma de verdade (evita
#    sobrescrever um mirror interno/Satellite que porventura já esteja
#    funcionando).
# 2) Máquinas do cliente costumam ter OUTROS repos de terceiros já configurados
#    (ex: PostgreSQL/pgdg) que não têm nada a ver com o RNRemote — se um deles
#    estiver com problema (chave GPG desatualizada, offline, etc.), o yum aborta
#    a operação INTEIRA por padrão, mesmo repo/base/epel funcionando normalmente
#    (achado real: instalação travou no `srv01ad01` por causa só do `pgdg-common`
#    com falha de assinatura). `--setopt=skip_if_unavailable=true` faz o yum
#    pular qualquer repo problemático em vez de abortar tudo — resolve essa
#    classe inteira de problema (não só pgdg) sem precisar identificar/desativar
#    repositórios de terceiros um por um.
# Em nenhum dos dois casos é exigido nenhum passo manual do usuário.
YUM_OPTS="--setopt=skip_if_unavailable=true"

fix_yum_repos_if_broken() {
    if ! yum makecache -q $YUM_OPTS &>/dev/null; then
        warn "Repositórios YUM padrão não respondem (mirrorlist.centos.org foi desligado após o fim do suporte do CentOS 7) — redirecionando para vault.centos.org..."
        sed -i \
            -e 's/mirror\.centos\.org/vault.centos.org/g' \
            -e 's/^#.*baseurl=http/baseurl=http/g' \
            -e 's/^mirrorlist=http/#mirrorlist=http/g' \
            /etc/yum.repos.d/CentOS-*.repo 2>/dev/null || true
        yum clean all -q
        if yum makecache -q $YUM_OPTS &>/dev/null; then
            ok "Repositórios YUM redirecionados para vault.centos.org"
        else
            err "Repositórios YUM continuam inacessíveis mesmo após redirecionar para vault.centos.org. Verifique a conectividade/DNS deste servidor."
        fi
    fi
}

# ── Garante python3 e pip (via EPEL — CentOS 7 não tem python3 no repo base) ──
echo -e "${BOLD}[1/5] Verificando Python 3...${RESET}"
if ! command -v python3 &>/dev/null; then
    fix_yum_repos_if_broken
    info "Instalando epel-release + python3..."
    yum install -y epel-release -q $YUM_OPTS
    yum install -y python3 python3-pip -q $YUM_OPTS
fi
if ! command -v pip3 &>/dev/null && ! python3 -m pip --version &>/dev/null 2>&1; then
    info "Instalando python3-pip..."
    yum install -y epel-release -q $YUM_OPTS 2>/dev/null || true
    yum install -y python3-pip -q $YUM_OPTS
fi
PYTHON=$(command -v python3)
ok "Python 3 OK ($($PYTHON --version 2>&1))"

# ── Dependência Python (só websockets — o navegador headless usa CDP puro) ────
echo -e "\n${BOLD}[2/5] Verificando dependências Python...${RESET}"
if ! $PYTHON -c "import websockets" 2>/dev/null; then
    info "Instalando websockets..."
    $PYTHON -m pip install --quiet websockets 2>/dev/null || \
    $PYTHON -m pip install --quiet websockets --user 2>/dev/null || \
    err "Falha ao instalar 'websockets'. Execute manualmente: pip3 install websockets"
fi
ok "Dependências Python OK"

# ── Detecta versão local/remota (pra decidir se é instalação nova ou update) ──
LOCAL_VERSION=""
if [ -f "$INSTALL_DIR/agent.py" ]; then
    LOCAL_VERSION=$(grep -oP 'AGENT_VERSION\s*=\s*"\K[^"]+' "$INSTALL_DIR/agent.py" 2>/dev/null || true)
fi
REMOTE_VERSION=$(curl -fsSL --max-time 10 "$PANEL_URL/api/agent/version" 2>/dev/null \
    | grep -oP '"linux"\s*:\s*"\K[^"]+' || true)

echo -e "\n  Versão local  : ${DIM}${LOCAL_VERSION:-desconhecida}${RESET}"
echo -e "  Versão remota : ${DIM}${REMOTE_VERSION:-indisponível}${RESET}\n"

# ── Caso 1: serviço já está rodando → apenas atualiza ─────────────────────────
if systemctl is-active --quiet "$SERVICE" 2>/dev/null; then

    if [ -n "$REMOTE_VERSION" ] && [ "$LOCAL_VERSION" = "$REMOTE_VERSION" ]; then
        ok "Agente já está na versão mais recente (${REMOTE_VERSION}) e rodando."
        exit 0
    fi

    echo -e "${BOLD}[3/5] Atualizando agent.py...${RESET}"
    CFG_AGENT_ID=$(python3 -c "import json; d=json.load(open('$CONF_DIR/agent.json')); print(d.get('agent_id',''))" 2>/dev/null || true)
    CFG_BINDING=$(python3 -c "import json; d=json.load(open('$CONF_DIR/agent.json')); print(d.get('binding_secret',''))" 2>/dev/null || true)
    BINDING_HASH=$(echo -n "${CFG_BINDING}${CFG_AGENT_ID}" | sha256sum | awk '{print $1}')
    if curl -fsSL --max-time 30 \
        -H "X-Agent-Id: ${CFG_AGENT_ID}" \
        -H "X-Binding-Token: ${BINDING_HASH}" \
        "$PANEL_URL/api/agents/download/agent.py" -o "$INSTALL_DIR/agent.py.new" 2>/dev/null; then
        SIZE=$(wc -c < "$INSTALL_DIR/agent.py.new")
        if [ "$SIZE" -lt 5000 ]; then
            rm -f "$INSTALL_DIR/agent.py.new"
            err "Arquivo baixado parece inválido ($SIZE bytes). Abortando."
        fi
        mv "$INSTALL_DIR/agent.py.new" "$INSTALL_DIR/agent.py"
        chmod +x "$INSTALL_DIR/agent.py"
        NEW_VER=$(grep -oP 'AGENT_VERSION\s*=\s*"\K[^"]+' "$INSTALL_DIR/agent.py" 2>/dev/null || true)
        ok "agent.py atualizado${NEW_VER:+ para v${NEW_VER}}"
    else
        err "Não foi possível baixar agent.py do painel ($PANEL_URL)"
    fi

    echo -e "\n${BOLD}[4/5] Reiniciando serviço...${RESET}"
    systemctl restart "$SERVICE"
    sleep 2
    ok "Serviço ${SERVICE} reiniciado"

    echo -e "\n${BOLD}[5/5] Verificando...${RESET}"
    if systemctl is-active --quiet "$SERVICE"; then
        ok "Serviço ${SERVICE} rodando"
    else
        echo -e "  ${RED}✘${RESET}  Serviço não iniciou. Verifique com:"
        echo -e "      journalctl -u ${SERVICE} -n 30"
        exit 1
    fi

    echo -e "\n${GREEN}${BOLD}╔══════════════════════════════════════════╗"
    echo -e "║        Atualização concluída!            ║"
    echo -e "╚══════════════════════════════════════════╝${RESET}"
    echo -e "\n  Serviço : ${CYAN}${SERVICE}${RESET}"
    echo -e "  Versão  : ${DIM}${NEW_VER:-${REMOTE_VERSION}}${RESET}\n"
    exit 0
fi

# ── Caso 2: instalação nova ────────────────────────────────────────────────────

echo -e "${BOLD}[3/5] Registrando agente no painel...${RESET}"
echo -e "  ${DIM}Informe as credenciais de administrador do painel RNRemote${RESET}\n"

read -rp "  E-mail do admin: " ADMIN_EMAIL
[ -z "$ADMIN_EMAIL" ] && err "E-mail é obrigatório."

read -rsp "  Senha do admin: " ADMIN_PASS
echo
[ -z "$ADMIN_PASS" ] && err "Senha é obrigatória."

DEFAULT_NICKNAME=$(hostname 2>/dev/null || echo "agente")
read -rp "  Nome desta máquina [${DEFAULT_NICKNAME}]: " INPUT_NICK
NICKNAME="${INPUT_NICK:-$DEFAULT_NICKNAME}"

read -rsp "  Senha de acesso ao agente (usada para conectar): " ACCESS_PASS
echo
[ -z "$ACCESS_PASS" ] && err "Senha de acesso é obrigatória."

info "Autenticando no painel..."
LOGIN_RESP=$(curl -fsSL --max-time 15 -X POST "$PANEL_URL/api/login" \
    -H "Content-Type: application/json" \
    -d "{\"email\":\"${ADMIN_EMAIL}\",\"password\":\"${ADMIN_PASS}\"}" 2>/dev/null) || \
    err "Não foi possível conectar ao painel ($PANEL_URL)"

JWT=$(echo "$LOGIN_RESP" | grep -oP '"token"\s*:\s*"\K[^"]+' || true)
[ -z "$JWT" ] && err "Login falhou. Verifique e-mail e senha."
ok "Autenticado no painel"

info "Registrando agente..."
PROV_RESP=$(curl -sSL --max-time 15 -X POST "$PANEL_URL/api/agents/provision" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${JWT}" \
    -d "{\"nickname\":\"${NICKNAME}\",\"access_password\":\"${ACCESS_PASS}\"}" 2>/dev/null) || \
    err "Não foi possível conectar ao painel para registrar agente"

PROV_OK=$(echo "$PROV_RESP" | grep -oP '"ok"\s*:\s*\K(true|false)' || true)
PROV_ERR=$(echo "$PROV_RESP" | grep -oP '"error"\s*:\s*"\K[^"]+' || true)
AGENT_ID=$(echo "$PROV_RESP" | grep -oP '"agent_id"\s*:\s*"\K[^"]+' || true)
BINDING_SECRET=$(echo "$PROV_RESP" | grep -oP '"binding_secret"\s*:\s*"\K[^"]+' || true)

[ "$PROV_OK" != "true" ] && err "Falha ao registrar agente: ${PROV_ERR:-resposta inválida}. Verifique se o usuário '${ADMIN_EMAIL}' tem permissão 'Agentes - Criar' no painel."
[ -z "$AGENT_ID" ] && err "Falha ao registrar agente: agent_id não retornado. Resposta: $PROV_RESP"
ok "Agente registrado: ID ${AGENT_ID} | Nome: ${NICKNAME}"

# ── Baixa agent.py ─────────────────────────────────────────────────────────────
echo -e "\n${BOLD}[4/5] Baixando agent.py...${RESET}"

mkdir -p "$INSTALL_DIR"
if curl -fsSL --max-time 30 \
    -H "Authorization: Bearer ${JWT}" \
    "$PANEL_URL/api/agents/download/agent.py" -o "$INSTALL_DIR/agent.py.new" 2>/dev/null; then
    SIZE=$(wc -c < "$INSTALL_DIR/agent.py.new")
    if [ "$SIZE" -lt 5000 ]; then
        rm -f "$INSTALL_DIR/agent.py.new"
        err "Arquivo baixado parece inválido ($SIZE bytes). Abortando."
    fi
    mv "$INSTALL_DIR/agent.py.new" "$INSTALL_DIR/agent.py"
    chmod +x "$INSTALL_DIR/agent.py"
    NEW_VER=$(grep -oP 'AGENT_VERSION\s*=\s*"\K[^"]+' "$INSTALL_DIR/agent.py" 2>/dev/null || true)
    ok "agent.py baixado${NEW_VER:+ (v${NEW_VER})}"
else
    err "Não foi possível baixar agent.py de $PANEL_URL"
fi

# ── Cria configuração ──────────────────────────────────────────────────────────
mkdir -p "$CONF_DIR"
cat > "$CONF_DIR/agent.json" <<EOF
{
  "relay_url":      "wss://rnremote.joaoneto.tec.br/ws",
  "agent_id":       "${AGENT_ID}",
  "password":       "${ACCESS_PASS}",
  "binding_secret": "${BINDING_SECRET}"
}
EOF
chmod 600 "$CONF_DIR/agent.json"
ok "Config criada em $CONF_DIR/agent.json"

# ── Cria e inicia serviço ─────────────────────────────────────────────────────
echo -e "\n${BOLD}[5/5] Instalando serviço systemd...${RESET}"

cat > "$SVC_FILE" <<EOF
[Unit]
Description=RNRemote Agent
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0

[Service]
Type=simple
User=root
ExecStart=$PYTHON $INSTALL_DIR/agent.py --config $CONF_DIR/agent.json
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable "$SERVICE" --quiet
systemctl start "$SERVICE"
sleep 2

if systemctl is-active --quiet "$SERVICE"; then
    ok "Serviço ${SERVICE} rodando"
else
    echo -e "  ${RED}✘${RESET}  Serviço não iniciou. Verifique com:"
    echo -e "      journalctl -u ${SERVICE} -n 30"
    exit 1
fi

FINAL_VER=$(grep -oP 'AGENT_VERSION\s*=\s*"\K[^"]+' "$INSTALL_DIR/agent.py" 2>/dev/null || echo "desconhecida")

echo -e "\n${GREEN}${BOLD}╔══════════════════════════════════════════╗"
echo -e "║      Instalação concluída com sucesso!   ║"
echo -e "╚══════════════════════════════════════════╝${RESET}"
echo -e "\n  Serviço : ${CYAN}${SERVICE}${RESET}"
echo -e "  Agente  : ${DIM}${AGENT_ID} (${NICKNAME})${RESET}"
echo -e "  Versão  : ${DIM}${FINAL_VER}${RESET}"
echo -e "  Config  : ${DIM}${CONF_DIR}/agent.json${RESET}"
echo -e "\n  ${DIM}O agente está baixando o navegador (Chromium ou Firefox) em segundo plano agora — acompanhe com:${RESET}"
echo -e "  ${DIM}journalctl -u ${SERVICE} -f | grep -Ei 'chrom|firefox'${RESET}"
echo -e "  Logs    : ${DIM}journalctl -u ${SERVICE} -f${RESET}\n"
