#!/bin/bash

# Último ajuste por Maicon Antunes Luiz (maicon.luiz@thomsonreuters.com)
# Versão 6.8 - Correção de Compatibilidade (Fedora/RHEL) e Melhorias de UX
#
# Changelog:
# - CORRIGIDO: O serviço não iniciava em Fedora/RHEL9+ devido à ausência da biblioteca 'libnsl.so.1'.
#   Adicionado o pacote 'libnsl' à lista de dependências na instalação base.
# - MELHORADO: Adicionado 'less' e 'p7zip'/'p7zip-full' às dependências para garantir que as funções de log e backup funcionem.
# - MELHORADO: A função 'exibirLog' agora pausa e informa o usuário quando um arquivo de log não é encontrado,
#   em vez de simplesmente retornar ao menu.

# --- Funções auxiliares, Validação e Variáveis ---
msg_info() { tput setaf 2; echo "$1"; tput sgr0; }
msg_warning() { tput setaf 3; echo "[AVISO] $1"; tput sgr0; }
msg_error() { tput setaf 1; echo "[ERRO] $1"; tput sgr0; }
msg_success() { tput setaf 2; echo "[SUCESSO] $1"; tput sgr0; }
if [ "$EUID" -ne 0 ]; then msg_error "Por favor, execute como root." && exit 1; fi
BASE_DIR="/opt/sqlanywhere17"; CONF_DIR="$BASE_DIR/conf.d"; LOG_DIR="$BASE_DIR/log"
RUNNER_SCRIPT="/usr/local/sbin/sqlanywhere-runner"; TEMPLATE_SERVICE="/etc/systemd/system/sqlanywhere@.service"
DOWNLOAD_URL='https://download.dominiosistemas.com.br/instalacao/diversos/sybase17_linux_64/ASA-1700-7312-Linux-64.tar.gz'
COMPRESSED_FILE='ASA-1700-7312-Linux-64.tar.gz'
versaoSistema(){ msg_info '|       Versões homologadas SQL Anywhere 17          |'; msg_info '|----------------------------------------------------|'; msg_info '| Kernel: 2.6.18..; glibc 2.5..  |  Kernel: 3.2.0..; glibc 2.15..  |'; echo; if command -v ldd &>/dev/null; then glibc=$(ldd --version|awk '/ldd/{print $NF}'); msg_info "Info: glibc $glibc | Kernel $(uname -r)"; else msg_error "glibc não encontrado"; fi; echo; }
verificarMemoriaLivre(){ if [ -w /proc/sys/vm/drop_caches ]; then echo 3|sudo tee /proc/sys/vm/drop_caches >/dev/null 2>&1; fi; mem_free=$(grep MemFree /proc/meminfo|awk '{print $2}'); [ -z "$mem_free" ]&&return 1; mem_rec=$((($mem_free*80/100)/1024)); free -mh|grep -E 'Mem|buffers/cache|free'; msg_info "Memória livre real: ~${mem_rec} MB"; }
porta_livre(){ local s="${1:-2638}"; local p; for((p=s;p<s+100;p++)); do if ! ss -lnt|awk '{print $4}'|grep -q ":$p$"; then echo "$p" && return 0; fi; done; return 1; }
listarBancos(){ [ -d "$CONF_DIR" ] && ls "$CONF_DIR"/*.conf 2>/dev/null|xargs -n 1 basename|sed 's/\.conf$//' || return 1; }
liberar_ufw(){ msg_info "ufw: Liberando porta $1..."; ufw allow "$1"/tcp >/dev/null; ufw allow "$1"/udp >/dev/null; ufw reload >/dev/null; }
liberar_firewalld(){ msg_info "firewalld: Liberando porta $1..."; firewall-cmd --permanent --add-port="$1"/tcp >/dev/null; firewall-cmd --permanent --add-port="$1"/udp >/dev/null; firewall-cmd --reload >/dev/null; }
configurar_firewall() { local PORT="${1:?É necessário fornecer uma porta}"; if ! [[ "$PORT" =~ ^[0-9]+$ ]]; then msg_error "Porta inválida: $PORT"; return 1; fi; if command -v ufw &>/dev/null && systemctl is-active --quiet ufw; then liberar_ufw "$PORT"; elif command -v firewall-cmd &>/dev/null && systemctl is-active --quiet firewalld; then liberar_firewalld "$PORT"; else msg_warning "Nenhum firewall (ufw, firewalld) ativo."; fi; }

# --- Funções Principais (Completas e Corrigidas) ---

# <<< FUNÇÃO CORRIGIDA >>>
InstalacaoBase() {
    if [ -d "$BASE_DIR" ]; then msg_success "Base já instalada."&&sleep 2&&return; fi; clear; versaoSistema; mkdir -p "$BASE_DIR" "$CONF_DIR" "$LOG_DIR"
    
    # <<< CORREÇÃO APLICADA: Adicionadas dependências 'libnsl', 'less' e 'p7zip'. >>>
    msg_info "Instalando dependências (wget, tar, libnsl, less, p7zip)..."
    if command -v dnf &>/dev/null; then 
        dnf install -y wget tar libnsl p7zip less >/dev/null 2>&1
    elif command -v apt-get &>/dev/null; then 
        apt-get update >/dev/null 2>&1 && apt-get install -y wget tar libnsl2 less p7zip-full >/dev/null 2>&1
    else
        msg_warning "Gerenciador de pacotes não detectado (apt/dnf). A instalação de dependências pode falhar."
    fi
    
    if [ -f "/tmp/$COMPRESSED_FILE" ]; then tar -xf "/tmp/$COMPRESSED_FILE" -C /opt >/dev/null 2>&1; else wget -q --show-progress -O "$BASE_DIR/$COMPRESSED_FILE" "$DOWNLOAD_URL"||{ msg_error "Download falhou."&&rm -rf "$BASE_DIR"&&exit 1;}; tar -xf "$BASE_DIR/$COMPRESSED_FILE" -C /opt >/dev/null 2>&1; rm "$BASE_DIR/$COMPRESSED_FILE"; fi
    chmod +x -R "$BASE_DIR"; echo "source $BASE_DIR/setenv >/dev/null 2>&1" > /etc/profile.d/domsis.sh; chmod +x /etc/profile.d/domsis.sh
    cat > "$RUNNER_SCRIPT" <<'EOF'
#!/bin/bash
set -euo pipefail
DB_ID="${1:?Uso: sqlanywhere-runner <id>}"; CONF_FILE="/opt/sqlanywhere17/conf.d/${DB_ID}.conf"; [ -f "$CONF_FILE" ]||{ echo "Config não encontrado: $CONF_FILE">&2; exit 1; }; source "$CONF_FILE"
source /opt/sqlanywhere17/setenv >/dev/null 2>&1||true; : "${SERVER_NAME:?}" "${DB_PATH:?}" "${CACHE_MB:?}" "${PORT:?}"
LOG_FILE="/opt/sqlanywhere17/log/log_${SERVER_NAME}.txt"; EXTRA_OPTS="${EXTRA_OPTS:-}"
exec dbsrv17 -n "$SERVER_NAME" -c "${CACHE_MB}M" -o "$LOG_FILE" -x "tcpip(ServerPort=${PORT})" $EXTRA_OPTS "$DB_PATH"
EOF
    chmod 755 "$RUNNER_SCRIPT"
    cat > "$TEMPLATE_SERVICE" <<'EOF'
[Unit]
Description=SQL Anywhere 17 (Instância: %i)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/sbin/sqlanywhere-runner %i
KillSignal=SIGTERM
KillMode=control-group
TimeoutStopSec=300
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
    chmod 644 "$TEMPLATE_SERVICE"; systemctl daemon-reload; msg_success "Estrutura instalada!" && sleep 4
}
adicionarBanco() {
    clear; read -rp "ID p/ banco (ex: matriz): " ID; if [[ -z "$ID" || ! "$ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then msg_error "ID inválido."&&sleep 2&&return; fi
    if [ -f "$CONF_DIR/$ID.conf" ]; then msg_error "ID já existe."&&sleep 2&&return; fi; read -rp "Nome do servidor (-n): " NAME; [ -z "$NAME" ]&&{ msg_error "Nome inválido.";return; }
    while true; do
        msg_info "Buscando por 'contabil.db' em todo o sistema... (pode demorar)"
        mapfile -t files < <(find / -type f -iname "contabil.db" 2>/dev/null)
        
        if [ ${#files[@]} -gt 0 ]; then
            msg_info "Bancos de dados 'Contabil' encontrados:"
            echo "0. Digitar caminho manualmente"
            for i in "${!files[@]}"; do echo "$((i+1)). ${files[i]}"; done
            read -rp "Opção: " choice
            if [[ "$choice" =~ ^[0-9]+$ && "$choice" -le ${#files[@]} ]]; then
                [ "$choice" -eq 0 ] && read -rp "Caminho completo do .db: " DBFILE || DBFILE="${files[$((choice-1))]}"
            else
                msg_warning "Opção inválida." && continue
            fi
        else
            msg_warning "Nenhum arquivo 'contabil.db' encontrado."
            read -rp "Digite o caminho completo do arquivo de banco de dados (.db): " DBFILE
        fi
        [ -f "$DBFILE" ] && break || msg_error "Arquivo não existe."
    done
    verificarMemoriaLivre; read -rp "Cache (MB): " CACHE; [[ ! "$CACHE" =~ ^[0-9]+$ ]]&&{ msg_error "Inválido.";return; }; local port=$(porta_livre)
    read -rp "Porta (sugestão $port): " PORT; PORT="${PORT:-$port}"; [[ ! "$PORT" =~ ^[0-9]+$ ]]&&{ msg_error "Inválido.";return; }
    cat > "$CONF_DIR/$ID.conf" <<EOF
SERVER_NAME="$NAME"
DB_PATH="$DBFILE"
CACHE_MB="$CACHE"
PORT="$PORT"
EXTRA_OPTS=""
EOF
    configurar_firewall "$PORT"; systemctl daemon-reload; systemctl enable "sqlanywhere@$ID.service" >/dev/null 2>&1
    read -rp "Iniciar o banco '$ID' agora? [S/n]: " ans; if [[ "${ans:-S}" =~ ^[Ss]$ ]]; then systemctl start "sqlanywhere@$ID.service"&&sleep 1; systemctl status "sqlanywhere@$ID.service" --no-pager&&read -r -p "Pressione Enter..."; fi
}
realizarBackup() {
    clear; local bancos=($(listarBancos)); if [ ${#bancos[@]} -eq 0 ]; then msg_warning "Nenhum banco."&&sleep 2&&return; fi
    msg_info "Selecione o banco para copiar:"; select id in "${bancos[@]}" "Todos" "Cancelar"; do [ "$id" = "Cancelar" ]&&return; [ -n "$id" ]&&break; done
    read -rp "É necessário PARAR o(s) banco(s) para garantir a integridade da cópia. Continuar? [S/n]: " c; [[ ! "$c" =~ ^[Ss]$ ]]&&return
    if ! command -v 7z &>/dev/null; then msg_warning "Utilitário '7z' não encontrado. Tente reinstalar a base (opção 1)."; read -r -p "Pressione Enter..."; return; fi
    local alvos=(); [ "$id" = "Todos" ]&&alvos=("${bancos[@]}")||alvos=("$id")
    for i in "${alvos[@]}"; do source "$CONF_DIR/$i.conf"; systemctl stop "sqlanywhere@$i.service"; bdir="$(dirname "$(dirname "$DB_PATH")")/Backups"; mkdir -p "$bdir"; bn="$(date +"%Y%m%d")"; c=1; bkp="${bn}_${c}C.dom"; while [ -f "$bdir/$bkp" ]; do c=$((c+1)); bkp="${bn}_${c}C.dom"; done
    7z a -mx=4 "$bdir/$bkp" "$(dirname "$DB_PATH")"/* >/dev/null; systemctl start "sqlanywhere@$i.service"; done; msg_success "Cópias de segurança concluídas."; read -r -p "Pressione Enter..."
}
gerenciarParametros() {
    clear; local bancos=($(listarBancos)); if [ ${#bancos[@]} -eq 0 ]; then msg_warning "Nenhum banco."&&sleep 2&&return; fi
    msg_info "Selecione o banco:"; select id in "${bancos[@]}" "Cancelar"; do [ "$id" = "Cancelar" ]&&return; [ -n "$id" ]&&break; done
    local conf="$CONF_DIR/$id.conf"
    unset SERVER_NAME DB_PATH CACHE_MB PORT EXTRA_OPTS; source "$conf"
    local ti=0 sb=0 zt=0; [[ "$EXTRA_OPTS" = *"-ti 0"* ]] && ti=1; [[ "$EXTRA_OPTS" = *"-sb 0"* ]] && sb=1; [[ "$EXTRA_OPTS" = *"-zt"* ]] && zt=1
    while true; do clear; msg_info "Parâmetros para: '$id'"; echo "1) $([ $ti -eq 1 ]&&echo "[ATIVO]"||echo "[INATIVO]") Timeout Ociosidade (-ti 0)"; echo "2) $([ $sb -eq 1 ]&&echo "[ATIVO]"||echo "[INATIVO]") Ocultar Servidor (-sb 0)"; tput setaf 5; echo "3) $([ $zt -eq 1 ]&&echo "[ATIVO]"||echo "[INATIVO]") Log de Diagnóstico"; tput sgr0; echo "4) Salvar e Reiniciar"; echo "5) Cancelar"
        read -rp "Opção: " opt
        case $opt in
            1) ti=$((1-ti));; 2) sb=$((1-sb));;
            3) if [ $zt -eq 0 ]; then read -rp "Ligar log? Pode impactar perf. [s/N]: " c; [[ "$c" =~ ^[Ss]$ ]]&&zt=1; else zt=0; fi;;
            4) local opts=""; [ $ti -eq 1 ] && opts+="-ti 0"; [ $sb -eq 1 ] && { [ -n "$opts" ] && opts+=" "; opts+="-sb 0"; }; [ $zt -eq 1 ] && { [ -n "$opts" ] && opts+=" "; opts+="-zt -zl -zr all -zn 20 -zs 500m -zo $LOG_DIR/req_${SERVER_NAME}.txt"; }
               cat > "$conf" <<EOF
SERVER_NAME="$SERVER_NAME"
DB_PATH="$DB_PATH"
CACHE_MB="$CACHE_MB"
PORT="$PORT"
EXTRA_OPTS="$opts"
EOF
               if grep -q "EXTRA_OPTS=\"$opts\"" "$conf"; then msg_success "Salvo! EXTRA_OPTS='$opts'"; else msg_error "ERRO AO SALVAR!"; read -r -p "Pressione Enter..."; return; fi
               systemctl restart "sqlanywhere@$id.service" && sleep 2; systemctl status "sqlanywhere@$id.service" --no-pager; read -r -p "Pressione Enter..."; return;;
            5) return;; *) continue;; esac
    done
}
Desinstalacao() { read -rp "Isto removerá a instalação do SQL Anywhere, mas NÃO os arquivos de banco de dados. Continuar? [S/n]: " c; [[ "$c" =~ ^[Ss]$ ]] || return; for id in $(listarBancos); do systemctl stop "sqlanywhere@$id.service" >/dev/null 2>&1; systemctl disable "sqlanywhere@$id.service" >/dev/null 2>&1; done; rm -f "$TEMPLATE_SERVICE" "$RUNNER_SCRIPT" /etc/profile.d/domsis.sh; systemctl daemon-reload; rm -rf "$BASE_DIR"; msg_success "Desinstalado." && sleep 3; }
gerenciarBancos() { clear; local bancos=($(listarBancos)); if [ ${#bancos[@]} -eq 0 ]; then msg_warning "Nenhum banco."&&sleep 2&&return; fi; local AL="$1" AC="$2"; msg_info "--- $AL ---"; select id in "${bancos[@]}" "Todos" "Cancelar"; do case $id in "Cancelar") return;; "Todos") for i in "${bancos[@]}"; do systemctl "$AC" "sqlanywhere@$i.service"; done;break;; *) if [ -n "$id" ]; then if [ "$AC" = "status" ]; then systemctl "$AC" "sqlanywhere@$id.service" --no-pager; else systemctl "$AC" "sqlanywhere@$id.service"; fi; fi;break;; esac; done; read -r -p "Pressione Enter..."; }

# <<< FUNÇÃO CORRIGIDA >>>
exibirLog() {
    clear; local b=($(listarBancos)); if [ ${#b[@]} -eq 0 ]; then msg_warning "Nenhum banco configurado."; sleep 2; return; fi
    msg_info "Selecione o banco para ver o log:"; 
    select id in "${b[@]}" "Cancelar"; do 
        if [ "$id" = "Cancelar" ]; then 
            return
        fi
        if [ -n "$id" ]; then 
            source "$CONF_DIR/$id.conf"
            log="$LOG_DIR/log_${SERVER_NAME}.txt"
            if [ -f "$log" ]; then 
                less +F "$log"
            else 
                # <<< CORREÇÃO APLICADA: Pausa para o usuário ler a mensagem. >>>
                msg_warning "Arquivo de log não encontrado em: $log"
                msg_info "Isso pode ocorrer se o serviço nunca iniciou com sucesso."
                read -r -p "Pressione Enter para continuar..."
            fi
        fi
        break
    done
}

coletarDiagnosticos() {
    clear
    msg_info "Iniciando coleta de diagnósticos..."
    local d="/tmp/diag_$(date +%s)"
    local f="/tmp/diag_$(hostname).tar.gz"

    msg_info "Diretório de trabalho temporário: $d"
    mkdir -p "$d"

    msg_info "Coletando logs do SQL Anywhere de '$LOG_DIR'..."
    cp -r "$LOG_DIR" "$d/logs" >/dev/null 2>&1

    msg_info "Coletando informações do sistema..."
    echo " - Data e hora atual" > "$d/sys.txt"
    date >> "$d/sys.txt" && echo >> "$d/sys.txt"
    echo " - Informações do Kernel e Arquitetura (uname -a)" >> "$d/sys.txt"
    uname -a >> "$d/sys.txt" && echo >> "$d/sys.txt"
    echo " - Detalhes da distribuição Linux (/etc/os-release)" >> "$d/sys.txt"
    cat /etc/os-release >> "$d/sys.txt" && echo >> "$d/sys.txt"
    echo " - Versão da Glibc (ldd --version)" >> "$d/sys.txt"
    ldd --version 2>/dev/null >> "$d/sys.txt" && echo >> "$d/sys.txt"
    echo " - Processos do SQL Anywhere em execução (ps)" >> "$d/sys.txt"
    ps -aux | grep "[d]bsrv17" >> "$d/sys.txt" && echo >> "$d/sys.txt"
    echo " - Uso de memória atual (free -h)" >> "$d/sys.txt"
    free -h >> "$d/sys.txt" && echo >> "$d/sys.txt"
    
    msg_info "Informações salvas em: $d/sys.txt"
    
    msg_info "Compactando todos os dados coletados para o arquivo final..."
    tar -czf "$f" -C "$(dirname "$d")" "$(basename "$d")"

    if [ $? -eq 0 ]; then
        rm -rf "$d"
        msg_success "Arquivo de diagnóstico gerado com sucesso!"
        msg_info "Localização do arquivo: $f"
    else
        msg_error "Ocorreu um erro ao gerar o arquivo de diagnóstico."
    fi

    read -r -p "Pressione Enter para voltar ao menu principal..."
}

# --- Menu Principal ---
Menu() {
    clear; tput setaf 1; echo "  ##### Gerenciador SQL Anywhere 17 (v6.8 - Compatibilidade) #####"; tput sgr0
    echo ' --- Instalação & Backup ---' ; tput setaf 2; echo ' 1) Instalar Base'; tput sgr0; echo ' 2) Adicionar Banco'; tput setaf 2; echo ' 3) Realizar cópia do banco de dados em produção'; tput sgr0; echo ' 4) Desinstalar Tudo (O banco de dados não será excluído)'
    echo ' --- Gerenciamento de Serviços ---'; tput setaf 2; echo ' 5) Iniciar banco de dados (Serviço)'; tput sgr0; echo ' 6) Parar banco de dados (Serviço)'; tput setaf 2; echo ' 7) Reiniciar banco de dados (Serviço)'; tput sgr0; echo ' 8) Status do banco de dados (Serviço)'
    echo ' --- Ferramentas & Diagnóstico ---'; tput setaf 2; echo ' 9) Exibir Log'; tput setaf 5; echo '10) Parâmetros Avançados'; tput sgr0; echo '11) Configurar Firewall'; tput setaf 5; echo '12) Coletar Diagnósticos'; tput sgr0; tput setaf 2; echo '13) Sair'; tput sgr0
    read -rp "Opção: " var; case $var in 1) InstalacaoBase;; 2) adicionarBanco;; 3) realizarBackup;; 4) Desinstalacao;; 5) gerenciarBancos "Iniciar Banco de Dados" "start";; 6) gerenciarBancos "Parar Banco de Dados" "stop";; 7) gerenciarBancos "Reiniciar Banco de Dados" "restart";; 8) gerenciarBancos "Ver Status do Banco" "status";; 9) exibirLog;; 10) gerenciarParametros;; 11) clear; b=($(listarBancos)); if [ ${#b[@]} -eq 0 ]; then return; fi; msg_info "Selecione o banco:"; select i in "${b[@]}"; do if [ -n "$i" ]; then source "$CONF_DIR/$i.conf"; configurar_firewall "$PORT"; break; fi; done; read -r -p "Enter...";; 12) coletarDiagnosticos;; 13) exit 0;; *) continue;; esac
}
while true; do Menu; done