#!/usr/bin/env bash
# Absolute DB v7.5.2
# Copyright (c) 2024-2026 D.H.Maree. All rights reserved.
# Author/Creator: David H Maree
# Owner: D.H.Maree (ABN 21 498 105 915) — sole IP holder
# Licensed to: SupportCALL AU — primary distributor
# SPDX-License-Identifier: BSL-1.1
# https://absolutedb.com/

# https://absolutedb.com/downloads/install-rhel.sh
# Copyright 2024–2026 SupportCALL AU & D.H.Maree — SPDX-License-Identifier: BSL-1.1
#
# Supported distros:
#   RHEL 8 / 9
#   CentOS Stream 8 / 9
#   AlmaLinux 8 / 9
#   Rocky Linux 8 / 9
#   Fedora 38 / 39 / 40
#
# Usage:
#   bash install-rhel.sh [OPTIONS]
#
# Options:
#   --no-service        Skip systemd service creation
#   --no-test           Skip post-install verification tests
#   --uninstall         Remove Absolute DB from this system
#   --prefix=<path>     Override installation prefix (default: /usr/local)
#   --branch=<name>     Clone a specific git branch (default: main)
#   --help              Show this help message

set -euo pipefail

# ---------------------------------------------------------------------------
# Global constants
# ---------------------------------------------------------------------------
VERSION="7.5.2"
REPO="https://github.com/supportcall/AbsoluteDB.git"
INSTALL_DIR="${HOME}/AbsoluteDB"
PREFIX="/usr/local"
BIN_DIR="${PREFIX}/bin"
DATA_DIR="/var/lib/absdb"
LOG_DIR="/var/log/absdb"
SERVICE_USER="absdb"
PG_PORT=5432
REST_PORT=8080
GRPC_PORT=9090
BRANCH="main"
TOTAL_STEPS=10

# Flags (may be overridden by CLI args)
DO_SERVICE=true
DO_TEST=true
DO_UNINSTALL=false

# Package manager (detected at runtime: dnf or yum)
PKG_MGR=""

# ---------------------------------------------------------------------------
# Colors and output helpers
# ---------------------------------------------------------------------------
RED='\033[0;31m'
GRN='\033[0;32m'
YLW='\033[0;33m'
BLU='\033[0;34m'
CYN='\033[0;36m'
MAG='\033[0;35m'
BOLD='\033[1m'
DIM='\033[2m'
NC='\033[0m'

# Disable colors when not a terminal
if [ ! -t 1 ]; then
    RED=''; GRN=''; YLW=''; BLU=''; CYN=''; MAG=''; BOLD=''; DIM=''; NC=''
fi

info()  { echo -e "${BLU}[INFO]${NC}  $*"; }
ok()    { echo -e "${GRN}[ OK ]${NC}  $*"; }
warn()  { echo -e "${YLW}[WARN]${NC}  $*"; }
step()  { echo -e "\n${BOLD}${CYN}━━━ Step ${1}/${TOTAL_STEPS}: ${2} ${NC}"; }
hdr()   { echo -e "${BOLD}${MAG}$*${NC}"; }

die() {
    echo -e "\n${RED}${BOLD}[FAIL]${NC}${RED}  $* ${NC}" >&2
    echo -e "\n${BOLD}${YLW}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${BOLD}${YLW}║               TROUBLESHOOTING GUIDE                         ║${NC}"
    echo -e "${BOLD}${YLW}╚══════════════════════════════════════════════════════════════╝${NC}"
    cat >&2 <<'TROUBLE'

1.  sudo not found
    → As root: dnf install -y sudo   (RHEL 8/9, Fedora)
    →          yum install -y sudo   (RHEL 7 / older CentOS)
    → Grant access: usermod -aG wheel $USER && newgrp wheel
    → For passwordless sudo: echo "$USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/$USER

2.  gcc not found / GCC too old (need ≥ 9)
    → RHEL 8/9 / AlmaLinux / Rocky:
        sudo dnf install -y gcc-toolset-11
        scl enable gcc-toolset-11 bash   # activate toolset
    → Or use devtoolset on older RHEL:
        sudo dnf install -y devtoolset-11-gcc devtoolset-11-gcc-c++
        source /opt/rh/devtoolset-11/enable
    → Fedora: sudo dnf install -y gcc-c++ (ships GCC 13+)

3.  git not found
    → sudo dnf install -y git   (or yum install -y git)

4.  DNS failure / no internet
    → ping -c1 8.8.8.8           # test network layer
    → cat /etc/resolv.conf        # check DNS resolver
    → nmcli general connectivity  # NetworkManager check
    → systemctl restart NetworkManager

5.  SSL certificate error (git clone fails)
    → sudo dnf install -y ca-certificates && sudo update-ca-trust
    → Or: git -c http.sslVerify=false clone <repo>
    → Corporate proxy: export https_proxy=http://proxy.corp:3128/

6.  make not found
    → sudo dnf groupinstall -y "Development Tools"
    → sudo dnf install -y make

7.  Permission denied for /usr/local/bin
    → Run with sudo or as root
    → Or: bash install-rhel.sh --prefix=$HOME/.local
    →     echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

8.  Port 5432 already in use
    → sudo ss -tlnp | grep 5432
    → sudo systemctl stop postgresql     # stop conflicting PostgreSQL
    → Or: sudo firewall-cmd --add-port=5432/tcp --permanent --zone=public
    →     sudo firewall-cmd --reload

9.  systemd not available (Docker containers)
    → Use --no-service flag
    → Start manually: absdb-server --data-dir=/var/lib/absdb --daemon

10. libm.so.6 not found at runtime
    → sudo dnf install -y glibc  (provides libm)
    → sudo ldconfig

11. Test failures / resource limits
    → ulimit -n 65536
    → cat /proc/sys/fs/file-max   # system-wide limit
    → sudo sysctl -w fs.file-max=200000

12. WSL2 specific notes
    → systemd in WSL2 requires Windows 11 Build 22000+ and WSL 0.67.6+
    → Add to /etc/wsl.conf: [boot] \n systemd=true
    → Then: wsl --shutdown && re-open terminal
    → RHEL-based images on WSL2 may need: sudo dnf install -y systemd

13. Running as root (Docker containers)
    → SERVICE_USER will still be created; use --no-service
    → Docker: mount /var/lib/absdb as a volume for persistence

14. absdb command not found after install
    → echo $PATH | grep -q /usr/local/bin || echo "MISSING"
    → echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.bashrc
    → source ~/.bashrc
    → Or use full path: /usr/local/bin/absdb --version

15. Disk space issues
    → df -h /usr/local /var /tmp
    → Minimum: 512 MB free
    → du -sh /var/lib/absdb

16. SELinux blocking absdb
    → Check: getenforce  (should be Permissive or Enforcing)
    → Temporary: sudo setenforce 0
    → Permanent: sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
    → Or add policy: sudo ausearch -c absdb --raw | audit2allow -M absdb
    →                sudo semodule -i absdb.pp
    → Check denials: sudo ausearch -m avc -ts today | grep absdb
    → Restore context: sudo restorecon -Rv /usr/local/bin/absdb /var/lib/absdb

17. Firewall blocking ports
    → sudo firewall-cmd --state    # check if running
    → Open PostgreSQL port:
        sudo firewall-cmd --add-port=5432/tcp --permanent --zone=public
    → Open REST port:
        sudo firewall-cmd --add-port=8080/tcp --permanent --zone=public
    → Open gRPC port:
        sudo firewall-cmd --add-port=9090/tcp --permanent --zone=public
    → Apply changes:
        sudo firewall-cmd --reload
    → Or disable temporarily: sudo systemctl stop firewalld

18. EPEL repository issues
    → RHEL 8: sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
    → RHEL 9: sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
    → AlmaLinux/Rocky: sudo dnf install -y epel-release
    → After installing EPEL: sudo dnf update -y
    → If subscription issues on RHEL: sudo subscription-manager repos --enable=codeready-builder-for-rhel-9-$(arch)-rpms

19. Proxy environment
    → export http_proxy=http://proxy.corp:3128/
    → export https_proxy=http://proxy.corp:3128/
    → export no_proxy=localhost,127.0.0.1,::1
    → For dnf: /etc/dnf/dnf.conf → add: proxy=http://proxy.corp:3128/
    → For git: git config --global http.proxy http://proxy.corp:3128/

TROUBLE
    echo -e "${DIM}Full log: /tmp/absdb-install-$$.log${NC}" >&2
    echo -e "${DIM}Support:  https://absolutedb.com/support  |  community@absolutedb.com${NC}" >&2
    exit 1
}

# Redirect all output to log file as well
exec > >(tee -a /tmp/absdb-install-$$.log) 2>&1

# ---------------------------------------------------------------------------
# Banner
# ---------------------------------------------------------------------------
print_banner() {
    echo -e "${BOLD}${CYN}"
    cat <<'BANNER'
  █████╗ ██████╗ ███████╗ ██████╗ ██╗     ██╗   ██╗████████╗███████╗    ██████╗ ██████╗
 ██╔══██╗██╔══██╗██╔════╝██╔═══██╗██║     ██║   ██║╚══██╔══╝██╔════╝    ██╔══██╗██╔══██╗
 ███████║██████╔╝███████╗██║   ██║██║     ██║   ██║   ██║   █████╗      ██║  ██║██████╔╝
 ██╔══██║██╔══██╗╚════██║██║   ██║██║     ██║   ██║   ██║   ██╔══╝      ██║  ██║██╔══██╗
 ██║  ██║██████╔╝███████║╚██████╔╝███████╗╚██████╔╝   ██║   ███████╗    ██████╔╝██████╔╝
 ╚═╝  ╚═╝╚═════╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝    ╚═╝   ╚══════╝    ╚═════╝ ╚═════╝
BANNER
    echo -e "${NC}"
    echo -e "${BOLD}  Absolute DB v${VERSION}  —  RHEL / CentOS / Fedora / AlmaLinux / Rocky Installer${NC}"
    echo -e "${DIM}  Unified AI-native database platform  |  https://absolutedb.com${NC}"
    echo -e "${DIM}  Copyright 2024–2026 SupportCALL AU & D.H.Maree  |  BSL-1.1${NC}"
    echo ""
    echo -e "${DIM}  Install log: /tmp/absdb-install-$$.log${NC}"
    echo ""
}

# ---------------------------------------------------------------------------
# Argument parsing
# ---------------------------------------------------------------------------
parse_args() {
    for arg in "$@"; do
        case "$arg" in
            --no-service)   DO_SERVICE=false ;;
            --no-test)      DO_TEST=false ;;
            --uninstall)    DO_UNINSTALL=true ;;
            --prefix=*)     PREFIX="${arg#*=}"; BIN_DIR="${PREFIX}/bin" ;;
            --branch=*)     BRANCH="${arg#*=}" ;;
            --help|-h)
                echo "Usage: bash install-rhel.sh [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  --no-service        Skip systemd service creation"
                echo "  --no-test           Skip post-install verification"
                echo "  --uninstall         Remove Absolute DB from this system"
                echo "  --prefix=<path>     Override install prefix (default: /usr/local)"
                echo "  --branch=<name>     Clone specific git branch (default: main)"
                echo "  --help              Show this help"
                exit 0
                ;;
            *)
                warn "Unknown argument: $arg  (ignored)"
                ;;
        esac
    done
}

# ---------------------------------------------------------------------------
# Sudo detection and helper
# ---------------------------------------------------------------------------
SUDO=""
setup_sudo() {
    if [ "$(id -u)" -eq 0 ]; then
        SUDO=""
        info "Running as root — sudo not required."
        return
    fi

    if ! command -v sudo >/dev/null 2>&1; then
        die "sudo is not installed. As root run: dnf install -y sudo && usermod -aG wheel $USER"
    fi

    if ! sudo -n true 2>/dev/null; then
        info "This installer requires sudo privileges. You may be prompted for your password."
        sudo -v || die "sudo authentication failed. Ensure your user is in the 'wheel' group."
    fi

    SUDO="sudo"
    ok "sudo access confirmed."
}

# ---------------------------------------------------------------------------
# Detect package manager (dnf preferred; fall back to yum)
# ---------------------------------------------------------------------------
detect_pkg_manager() {
    if command -v dnf >/dev/null 2>&1; then
        PKG_MGR="dnf"
        ok "Package manager: dnf"
    elif command -v yum >/dev/null 2>&1; then
        PKG_MGR="yum"
        warn "dnf not found — falling back to yum."
    else
        die "Neither dnf nor yum found. This installer requires an RPM-based system."
    fi
}

# ---------------------------------------------------------------------------
# Distro detection
# ---------------------------------------------------------------------------
DISTRO_ID=""
DISTRO_VERSION=""
DISTRO_VERSION_MAJOR=0
IS_FEDORA=false
IS_RHEL_COMPATIBLE=false
detect_distro() {
    if [ ! -f /etc/os-release ]; then
        warn "/etc/os-release not found — assuming RHEL-compatible."
        DISTRO_ID="rhel"
        DISTRO_VERSION="8"
        DISTRO_VERSION_MAJOR=8
        return
    fi

    # shellcheck disable=SC1091
    . /etc/os-release
    DISTRO_ID="${ID:-unknown}"
    DISTRO_VERSION="${VERSION_ID:-0}"
    DISTRO_VERSION_MAJOR=$(echo "$DISTRO_VERSION" | cut -d. -f1)

    case "$DISTRO_ID" in
        fedora)
            IS_FEDORA=true
            info "Distro: ${BOLD}Fedora ${DISTRO_VERSION}${NC}"
            ;;
        rhel|centos|almalinux|rocky|ol)
            IS_RHEL_COMPATIBLE=true
            info "Distro: ${BOLD}${NAME:-$DISTRO_ID} ${DISTRO_VERSION}${NC}"
            ;;
        *)
            # Check ID_LIKE
            if echo "${ID_LIKE:-}" | grep -qi "rhel\|fedora\|centos"; then
                IS_RHEL_COMPATIBLE=true
                warn "Unrecognised distro '${DISTRO_ID}' — treating as RHEL-compatible."
            else
                die "Unrecognised distro '${DISTRO_ID}'. This script supports RHEL/CentOS/Fedora/AlmaLinux/Rocky."
            fi
            ;;
    esac
}

# ---------------------------------------------------------------------------
# Systemd availability check
# ---------------------------------------------------------------------------
SYSTEMD_AVAILABLE=false
check_systemd() {
    if [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
        if systemctl is-system-running --quiet 2>/dev/null || \
           systemctl status --quiet 2>/dev/null; then
            SYSTEMD_AVAILABLE=true
        fi
    fi

    if [ "$SYSTEMD_AVAILABLE" = false ]; then
        warn "systemd is not active on this system (Docker / minimal container?)."
        warn "Service will not be installed. Start manually: absdb-server --daemon"
        DO_SERVICE=false
    fi
}

# ---------------------------------------------------------------------------
# SELinux detection
# ---------------------------------------------------------------------------
SELINUX_ENFORCING=false
check_selinux() {
    if command -v getenforce >/dev/null 2>&1; then
        local mode
        mode=$(getenforce 2>/dev/null || echo "Disabled")
        info "SELinux mode: ${mode}"
        if [ "$mode" = "Enforcing" ]; then
            SELINUX_ENFORCING=true
            warn "SELinux is Enforcing. If absdb fails to start, see troubleshooting item 16."
            warn "Quick fix: sudo setenforce 0  (then configure policy — see troubleshooting)"
        fi
    fi
}

# ---------------------------------------------------------------------------
# Firewalld detection
# ---------------------------------------------------------------------------
check_firewalld() {
    if command -v firewall-cmd >/dev/null 2>&1; then
        if systemctl is-active --quiet firewalld 2>/dev/null; then
            warn "firewalld is active. Ports ${PG_PORT}, ${REST_PORT}, ${GRPC_PORT} must be open."
            warn "Run after install:"
            warn "  sudo firewall-cmd --add-port=${PG_PORT}/tcp --permanent --zone=public"
            warn "  sudo firewall-cmd --add-port=${REST_PORT}/tcp --permanent --zone=public"
            warn "  sudo firewall-cmd --add-port=${GRPC_PORT}/tcp --permanent --zone=public"
            warn "  sudo firewall-cmd --reload"
        fi
    fi
}

# ---------------------------------------------------------------------------
# Disk space check
# ---------------------------------------------------------------------------
check_disk_space() {
    local required_kb=524288  # 512 MB
    local available_kb
    available_kb=$(df -k "${HOME}" 2>/dev/null | awk 'NR==2{print $4}' || echo 0)
    if [ "$available_kb" -lt "$required_kb" ]; then
        die "Insufficient disk space. Need ≥ 512 MB free in ${HOME}. Have: $(( available_kb / 1024 )) MB."
    fi
    ok "Disk space: $(( available_kb / 1024 )) MB available — sufficient."
}

# ---------------------------------------------------------------------------
# Network check (non-fatal)
# ---------------------------------------------------------------------------
check_network() {
    if ! ping -c1 -W3 8.8.8.8 >/dev/null 2>&1 && \
       ! curl -s --connect-timeout 5 https://github.com >/dev/null 2>&1; then
        warn "Cannot reach the internet. Check connectivity or proxy settings."
        warn "Set: export https_proxy=http://proxy.corp:3128/"
        warn "For dnf proxy: add 'proxy=http://proxy.corp:3128/' to /etc/dnf/dnf.conf"
    else
        ok "Network connectivity confirmed."
    fi
}

# ---------------------------------------------------------------------------
# Enable CodeReady Builder / PowerTools (provides devel packages on RHEL 8/9)
# ---------------------------------------------------------------------------
enable_crb_if_needed() {
    if [ "$IS_FEDORA" = true ]; then
        return  # Fedora doesn't need CRB
    fi

    # Try to enable CodeReady Builder (RHEL 9) or PowerTools (RHEL 8 / CentOS)
    if command -v subscription-manager >/dev/null 2>&1 && \
       subscription-manager status >/dev/null 2>&1; then
        # Registered RHEL
        if [ "$DISTRO_VERSION_MAJOR" -ge 9 ]; then
            $SUDO subscription-manager repos \
                --enable="codeready-builder-for-rhel-9-$(uname -m)-rpms" 2>/dev/null || true
        else
            $SUDO subscription-manager repos \
                --enable="codeready-builder-for-rhel-8-$(uname -m)-rpms" 2>/dev/null || true
        fi
    else
        # Community distros: use dnf config-manager
        if $SUDO $PKG_MGR install -y dnf-plugins-core 2>/dev/null; then
            if [ "$DISTRO_VERSION_MAJOR" -ge 9 ]; then
                $SUDO $PKG_MGR config-manager --set-enabled crb 2>/dev/null || \
                $SUDO $PKG_MGR config-manager --set-enabled powertools 2>/dev/null || true
            else
                $SUDO $PKG_MGR config-manager --set-enabled powertools 2>/dev/null || \
                $SUDO $PKG_MGR config-manager --set-enabled PowerTools 2>/dev/null || true
            fi
        fi
    fi
}

# ---------------------------------------------------------------------------
# Step 1 — System update and prerequisites
# ---------------------------------------------------------------------------
install_prerequisites() {
    step 1 "Installing prerequisites (${PKG_MGR})"

    # Update package cache
    info "Updating package cache..."
    $SUDO $PKG_MGR makecache -q 2>&1 || warn "$PKG_MGR makecache failed — continuing with cached metadata."

    # Enable CRB / PowerTools for devel headers on RHEL-compatible distros
    enable_crb_if_needed

    # Install Development Tools group
    info "Installing 'Development Tools' group..."
    $SUDO $PKG_MGR groupinstall -y "Development Tools" 2>&1 \
        || $SUDO $PKG_MGR install -y gcc gcc-c++ make 2>&1 \
        || warn "Development Tools group install had issues — attempting individual packages."

    # Core packages
    local pkgs=(
        gcc
        gcc-c++
        make
        git
        curl
        wget
        ca-certificates
        glibc-devel
        libgcc
        util-linux
        procps-ng
        lsb_release
        nmap-ncat
    )

    # Fedora vs RHEL-compatible differences
    if [ "$IS_FEDORA" = true ]; then
        pkgs+=(redhat-lsb-core)
    else
        # RHEL 8+ uses redhat-lsb-core from EPEL or equivalent
        $SUDO $PKG_MGR install -y redhat-lsb-core 2>/dev/null || true
    fi

    info "Installing packages: ${pkgs[*]}"
    # Install each package individually to avoid one missing package killing the whole install
    for pkg in "${pkgs[@]}"; do
        $SUDO $PKG_MGR install -y "$pkg" 2>/dev/null || warn "Package '$pkg' not available — skipping."
    done

    ok "Base packages installed."
}

# ---------------------------------------------------------------------------
# Step 2 — Ensure GCC ≥ 9
# ---------------------------------------------------------------------------
ensure_gcc() {
    step 2 "Verifying GCC version (need ≥ 9)"

    local gcc_ver=0
    if command -v gcc >/dev/null 2>&1; then
        gcc_ver=$(gcc -dumpversion 2>/dev/null | cut -d. -f1 || echo 0)
    fi

    if [ "$gcc_ver" -lt 9 ] 2>/dev/null; then
        warn "GCC $gcc_ver is too old (need ≥ 9). Installing GCC 11 via toolset..."

        if [ "$IS_FEDORA" = true ]; then
            $SUDO $PKG_MGR install -y gcc-c++ \
                || die "Failed to install GCC on Fedora."
        else
            # RHEL 8/9, AlmaLinux, Rocky — use gcc-toolset
            if $SUDO $PKG_MGR install -y gcc-toolset-11 gcc-toolset-11-gcc-c++ 2>/dev/null; then
                # Activate the toolset in current shell and for the build
                if [ -f /opt/rh/gcc-toolset-11/enable ]; then
                    # shellcheck disable=SC1091
                    source /opt/rh/gcc-toolset-11/enable
                    ok "gcc-toolset-11 activated."
                fi
            elif $SUDO $PKG_MGR install -y devtoolset-11-gcc devtoolset-11-gcc-c++ 2>/dev/null; then
                if [ -f /opt/rh/devtoolset-11/enable ]; then
                    # shellcheck disable=SC1091
                    source /opt/rh/devtoolset-11/enable
                    ok "devtoolset-11 activated."
                fi
            else
                warn "Could not install gcc-toolset-11. Build may fail with old GCC."
            fi
        fi
    fi

    # Final check
    command -v gcc >/dev/null 2>&1 || die "gcc not found after installation."
    gcc_ver=$(gcc -dumpversion | cut -d. -f1)
    ok "GCC ${gcc_ver} ready."
}

# ---------------------------------------------------------------------------
# Step 3 — Verify all tools are present
# ---------------------------------------------------------------------------
verify_tools() {
    step 3 "Verifying build tools"

    local tools=(gcc make git curl)
    for tool in "${tools[@]}"; do
        if ! command -v "$tool" >/dev/null 2>&1; then
            die "$tool is not available after installation. See troubleshooting."
        fi
        ok "$tool: $(command -v "$tool")"
    done
}

# ---------------------------------------------------------------------------
# Step 4 — Clone or update repository
# ---------------------------------------------------------------------------
clone_repository() {
    step 4 "Cloning Absolute DB v${VERSION} repository"

    if [ -d "$INSTALL_DIR" ]; then
        warn "Directory ${INSTALL_DIR} already exists — removing and recloning."
        rm -rf "$INSTALL_DIR" || die "Failed to remove existing directory: $INSTALL_DIR"
    fi

    info "Cloning ${REPO} (branch: ${BRANCH}) → ${INSTALL_DIR}"

    local clone_ok=false

    # First attempt: standard clone
    if git clone --depth=1 --branch "$BRANCH" "$REPO" "$INSTALL_DIR" 2>&1; then
        clone_ok=true
    else
        warn "Standard git clone failed. Retrying with SSL verification disabled..."
        if git -c http.sslVerify=false clone --depth=1 --branch "$BRANCH" "$REPO" "$INSTALL_DIR" 2>&1; then
            clone_ok=true
            warn "Cloned with SSL verification disabled. Fix CA bundle:"
            warn "  sudo $PKG_MGR install -y ca-certificates && sudo update-ca-trust"
        fi
    fi

    if [ "$clone_ok" = false ]; then
        die "git clone failed. Check internet connection, SSL certs, proxy, and EPEL (troubleshooting #18)."
    fi

    ok "Repository cloned to ${INSTALL_DIR}."
}

# ---------------------------------------------------------------------------
# Step 5 — Build
# ---------------------------------------------------------------------------
build_absdb() {
    step 5 "Building Absolute DB v${VERSION}"

    cd "$INSTALL_DIR" || die "Cannot enter ${INSTALL_DIR}"

    info "Running make clean..."
    make clean 2>&1 || warn "make clean failed — continuing anyway."

    info "Running make all..."
    make all 2>&1 || die "Build failed. Review errors above. Check troubleshooting for GCC/SELinux hints."

    # Verify binaries were produced
    for bin in absdb absdb-server; do
        local found
        found=$(find "$INSTALL_DIR" -maxdepth 3 -name "$bin" -type f 2>/dev/null | head -1 || true)
        if [ -z "$found" ]; then
            die "Binary '${bin}' not found after build. Build may have failed silently."
        fi
    done

    ok "Build completed successfully."
}

# ---------------------------------------------------------------------------
# Step 6 — Install binaries
# ---------------------------------------------------------------------------
install_binaries() {
    step 6 "Installing binaries to ${BIN_DIR}"

    $SUDO mkdir -p "$BIN_DIR" || die "Cannot create ${BIN_DIR}"

    for bin in absdb absdb-server; do
        local src=""
        for loc in \
            "${INSTALL_DIR}/${bin}" \
            "${INSTALL_DIR}/build/${bin}" \
            "${INSTALL_DIR}/out/${bin}" \
            "${INSTALL_DIR}/dist/${bin}"; do
            if [ -f "$loc" ] && [ -x "$loc" ]; then
                src="$loc"
                break
            fi
        done

        if [ -z "$src" ]; then
            warn "Binary '${bin}' not found — skipping."
            continue
        fi

        $SUDO install -m 755 "$src" "${BIN_DIR}/${bin}" \
            || die "Failed to install ${bin} to ${BIN_DIR}. See troubleshooting #7."
        ok "Installed: ${BIN_DIR}/${bin}"
    done

    # SELinux context restoration for installed binaries
    if command -v restorecon >/dev/null 2>&1; then
        $SUDO restorecon -v "${BIN_DIR}/absdb" "${BIN_DIR}/absdb-server" 2>/dev/null || true
        ok "SELinux context restored on binaries."
    fi

    # Ensure BIN_DIR is on PATH
    if ! echo "$PATH" | grep -q "${BIN_DIR}"; then
        warn "${BIN_DIR} is not in PATH. Adding to ~/.bashrc..."
        if ! grep -q "${BIN_DIR}" "${HOME}/.bashrc" 2>/dev/null; then
            echo "" >> "${HOME}/.bashrc"
            echo "# Absolute DB — added by installer" >> "${HOME}/.bashrc"
            echo "export PATH=\"${BIN_DIR}:\$PATH\"" >> "${HOME}/.bashrc"
        fi
        export PATH="${BIN_DIR}:${PATH}"
        ok "Added ${BIN_DIR} to PATH (effective after: source ~/.bashrc)"
    fi
}

# ---------------------------------------------------------------------------
# Step 7 — Create data and log directories, service user
# ---------------------------------------------------------------------------
setup_directories_and_user() {
    step 7 "Creating data directories and service user"

    # Create service user (system account, no login shell)
    if ! id "$SERVICE_USER" >/dev/null 2>&1; then
        $SUDO useradd \
            --system \
            --no-create-home \
            --shell /sbin/nologin \
            --comment "Absolute DB service account" \
            "$SERVICE_USER" \
            || die "Failed to create service user '${SERVICE_USER}'."
        ok "Service user '${SERVICE_USER}' created."
    else
        ok "Service user '${SERVICE_USER}' already exists."
    fi

    for dir in "$DATA_DIR" "$LOG_DIR"; do
        $SUDO mkdir -p "$dir" || die "Cannot create directory: $dir"
        $SUDO chown "${SERVICE_USER}:${SERVICE_USER}" "$dir" \
            || warn "Cannot chown ${dir}"
        $SUDO chmod 750 "$dir"
        ok "Directory: $dir"
    done

    # Set SELinux file contexts for data and log directories
    if command -v semanage >/dev/null 2>&1 && [ "$SELINUX_ENFORCING" = true ]; then
        $SUDO semanage fcontext -a -t var_lib_t "${DATA_DIR}(/.*)?" 2>/dev/null || true
        $SUDO semanage fcontext -a -t var_log_t "${LOG_DIR}(/.*)?" 2>/dev/null || true
        $SUDO restorecon -Rv "$DATA_DIR" "$LOG_DIR" 2>/dev/null || true
        ok "SELinux file contexts configured for data and log directories."
    fi
}

# ---------------------------------------------------------------------------
# Step 8 — Systemd service
# ---------------------------------------------------------------------------
install_service() {
    step 8 "Installing systemd service"

    if [ "$DO_SERVICE" = false ]; then
        info "Skipping service installation (--no-service or systemd unavailable)."
        return
    fi

    if [ "$SYSTEMD_AVAILABLE" = false ]; then
        warn "systemd is not running — skipping service installation."
        info "To start manually: ${BIN_DIR}/absdb-server --data-dir=${DATA_DIR} --log-dir=${LOG_DIR} --daemon"
        return
    fi

    local service_file="/etc/systemd/system/absdb.service"

    $SUDO tee "$service_file" > /dev/null <<UNIT
[Unit]
Description=Absolute DB v${VERSION} — Unified AI-Native Database Platform
Documentation=https://absolutedb.com/docs
After=network.target network-online.target
Wants=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=notify
User=${SERVICE_USER}
Group=${SERVICE_USER}
ExecStart=${BIN_DIR}/absdb-server \\
    --data-dir=${DATA_DIR} \\
    --log-dir=${LOG_DIR} \\
    --pg-port=${PG_PORT} \\
    --rest-port=${REST_PORT} \\
    --grpc-port=${GRPC_PORT}
ExecReload=/bin/kill -HUP \$MAINPID
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30
TimeoutStopSec=30

# Resource limits
LimitNOFILE=65536
LimitNPROC=4096

# Working directory
WorkingDirectory=${DATA_DIR}

# Logging
StandardOutput=append:${LOG_DIR}/absdb.log
StandardError=append:${LOG_DIR}/absdb-error.log
SyslogIdentifier=absdb

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectSystem=strict
ProtectHome=read-only
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=false
SystemCallArchitectures=native
SystemCallFilter=@system-service
ReadWritePaths=${DATA_DIR} ${LOG_DIR}
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
UNIT

    # SELinux context for unit file
    if command -v restorecon >/dev/null 2>&1; then
        $SUDO restorecon -v "$service_file" 2>/dev/null || true
    fi

    $SUDO systemctl daemon-reload \
        || warn "systemctl daemon-reload failed."

    $SUDO systemctl enable absdb.service \
        || warn "Failed to enable absdb.service."

    ok "systemd service installed: ${service_file}"
    ok "Service enabled (will start on boot)."

    # Start the service
    info "Starting absdb.service..."
    if $SUDO systemctl start absdb.service 2>&1; then
        ok "absdb.service started."
    else
        warn "Service failed to start immediately. Diagnostics:"
        warn "  sudo systemctl status absdb.service"
        warn "  journalctl -u absdb.service -n 50"
        warn "  cat ${LOG_DIR}/absdb-error.log"
        if [ "$SELINUX_ENFORCING" = true ]; then
            warn "SELinux may be blocking the process. See troubleshooting #16."
        fi
    fi
}

# ---------------------------------------------------------------------------
# Step 9 — Verify installation
# ---------------------------------------------------------------------------
verify_install() {
    step 9 "Verifying installation"

    if [ "$DO_TEST" = false ]; then
        info "Skipping verification (--no-test)."
        return
    fi

    if command -v absdb >/dev/null 2>&1; then
        local ver_out
        ver_out=$(absdb --version 2>&1 || true)
        ok "absdb CLI: ${ver_out}"
    else
        warn "absdb not found in PATH. Try: source ~/.bashrc"
    fi

    if command -v absdb-server >/dev/null 2>&1; then
        local sver_out
        sver_out=$(absdb-server --version 2>&1 || true)
        ok "absdb-server: ${sver_out}"
    else
        warn "absdb-server not found in PATH."
    fi

    if [ "$DO_SERVICE" = true ] && [ "$SYSTEMD_AVAILABLE" = true ]; then
        local attempts=6
        local port_open=false
        info "Waiting for server to accept connections on port ${PG_PORT}..."
        for i in $(seq 1 $attempts); do
            if nc -z 127.0.0.1 "$PG_PORT" 2>/dev/null; then
                port_open=true
                break
            fi
            sleep 2
        done

        if [ "$port_open" = true ]; then
            ok "Server is accepting connections on port ${PG_PORT}."
        else
            warn "Server does not appear to be listening on port ${PG_PORT} yet."
            warn "Check: sudo systemctl status absdb && journalctl -u absdb -n 30"
            if [ "$SELINUX_ENFORCING" = true ]; then
                warn "SELinux may be blocking. Run: sudo ausearch -m avc -ts recent | grep absdb"
            fi
        fi
    fi
}

# ---------------------------------------------------------------------------
# Step 10 — Final summary
# ---------------------------------------------------------------------------
print_summary() {
    step 10 "Installation complete"

    echo ""
    echo -e "${BOLD}${GRN}╔══════════════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${BOLD}${GRN}║         Absolute DB v${VERSION} — Successfully Installed!              ║${NC}"
    echo -e "${BOLD}${GRN}╚══════════════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    hdr "  Installation Summary"
    echo -e "  ${DIM}Binary (CLI):   ${NC}${BIN_DIR}/absdb"
    echo -e "  ${DIM}Binary (Server):${NC}${BIN_DIR}/absdb-server"
    echo -e "  ${DIM}Data directory: ${NC}${DATA_DIR}"
    echo -e "  ${DIM}Log directory:  ${NC}${LOG_DIR}"
    echo -e "  ${DIM}Service user:   ${NC}${SERVICE_USER}"
    echo -e "  ${DIM}PostgreSQL port:${NC}${PG_PORT}"
    echo -e "  ${DIM}REST API port:  ${NC}${REST_PORT}"
    echo -e "  ${DIM}gRPC port:      ${NC}${GRPC_PORT}"
    echo ""
    hdr "  Quick-Start Commands"
    echo -e "  ${CYN}# Connect with psql${NC}"
    echo -e "  psql -h 127.0.0.1 -p ${PG_PORT} -U absdb"
    echo ""
    echo -e "  ${CYN}# Run an inline SQL query${NC}"
    echo -e "  absdb --exec \"SELECT version();\""
    echo ""
    echo -e "  ${CYN}# REST API${NC}"
    echo -e "  curl http://127.0.0.1:${REST_PORT}/api/v1/query -d '{\"sql\":\"SELECT 1\"}'"
    echo ""
    echo -e "  ${CYN}# Web management console${NC}"
    echo -e "  open http://127.0.0.1:${REST_PORT}/console"
    echo ""
    if [ "$DO_SERVICE" = true ] && [ "$SYSTEMD_AVAILABLE" = true ]; then
        hdr "  Service Management"
        echo -e "  ${CYN}sudo systemctl start   absdb${NC}   # start"
        echo -e "  ${CYN}sudo systemctl stop    absdb${NC}   # stop"
        echo -e "  ${CYN}sudo systemctl restart absdb${NC}   # restart"
        echo -e "  ${CYN}sudo systemctl status  absdb${NC}   # status"
        echo -e "  ${CYN}journalctl -u absdb -f     ${NC}   # follow logs"
        echo ""
    else
        hdr "  Manual Start"
        echo -e "  ${CYN}absdb-server --data-dir=${DATA_DIR} --log-dir=${LOG_DIR} --daemon${NC}"
        echo ""
    fi
    if [ "$SELINUX_ENFORCING" = true ]; then
        hdr "  SELinux Notes"
        echo -e "  ${YLW}SELinux is Enforcing. If issues occur, see troubleshooting item 16.${NC}"
        echo -e "  ${YLW}Quick fix: sudo setenforce 0${NC}"
        echo ""
    fi
    hdr "  Next Steps"
    echo -e "  ${YLW}1. Open firewall ports for remote access:${NC}"
    if command -v firewall-cmd >/dev/null 2>&1; then
        echo -e "     ${CYN}sudo firewall-cmd --permanent --add-port=${PG_PORT}/tcp${NC}   ${DIM}# PostgreSQL wire${NC}"
        echo -e "     ${CYN}sudo firewall-cmd --permanent --add-port=${REST_PORT}/tcp${NC}   ${DIM}# REST API + Web console${NC}"
        echo -e "     ${CYN}sudo firewall-cmd --permanent --add-port=${GRPC_PORT}/tcp${NC}   ${DIM}# gRPC / HTTP/2${NC}"
        echo -e "     ${CYN}sudo firewall-cmd --permanent --add-port=6379/tcp${NC}   ${DIM}# Redis RESP3 (if enabled)${NC}"
        echo -e "     ${CYN}sudo firewall-cmd --reload${NC}"
    else
        echo -e "     ${CYN}sudo iptables -A INPUT -p tcp --dport ${PG_PORT} -j ACCEPT${NC}   ${DIM}# PostgreSQL wire${NC}"
        echo -e "     ${CYN}sudo iptables -A INPUT -p tcp --dport ${REST_PORT} -j ACCEPT${NC}   ${DIM}# REST API + Web console${NC}"
        echo -e "     ${CYN}sudo iptables -A INPUT -p tcp --dport ${GRPC_PORT} -j ACCEPT${NC}   ${DIM}# gRPC / HTTP/2${NC}"
        echo -e "     ${CYN}sudo iptables -A INPUT -p tcp --dport 6379 -j ACCEPT${NC}   ${DIM}# Redis RESP3 (if enabled)${NC}"
    fi
    echo ""
    echo -e "  ${YLW}2. Open the web management console:${NC}"
    echo -e "     ${CYN}http://localhost:${REST_PORT}/console${NC}"
    echo ""
    echo -e "  ${YLW}3. Enable TLS for production:${NC}"
    echo -e "     See ${DIM}https://absolutedb.com/docs/tls${NC}"
    echo ""
    hdr "  Documentation & Support"
    echo -e "  ${DIM}Docs:     ${NC}https://absolutedb.com/docs"
    echo -e "  ${DIM}Discord:  ${NC}https://discord.gg/absolutedb"
    echo -e "  ${DIM}Support:  ${NC}community@absolutedb.com"
    echo -e "  ${DIM}GitHub:   ${NC}${REPO}"
    echo ""
    if ! echo "$PATH" | grep -q "${BIN_DIR}"; then
        echo -e "  ${YLW}NOTE: Run${NC} source ~/.bashrc ${YLW}to update your PATH in this shell session.${NC}"
        echo ""
    fi
    echo -e "${BOLD}${GRN}  Enjoy Absolute DB v${VERSION}!${NC}"
    echo ""
}

# ---------------------------------------------------------------------------
# Uninstall
# ---------------------------------------------------------------------------
do_uninstall() {
    hdr "Uninstalling Absolute DB v${VERSION}..."

    if [ "$SYSTEMD_AVAILABLE" = true ] && \
       systemctl is-active --quiet absdb.service 2>/dev/null; then
        $SUDO systemctl stop absdb.service || true
        $SUDO systemctl disable absdb.service || true
        $SUDO rm -f /etc/systemd/system/absdb.service
        $SUDO systemctl daemon-reload || true
        ok "systemd service removed."
    fi

    for bin in absdb absdb-server; do
        if [ -f "${BIN_DIR}/${bin}" ]; then
            $SUDO rm -f "${BIN_DIR}/${bin}"
            ok "Removed ${BIN_DIR}/${bin}"
        fi
    done

    if [ -d "$INSTALL_DIR" ]; then
        rm -rf "$INSTALL_DIR"
        ok "Removed ${INSTALL_DIR}"
    fi

    warn "Data and logs NOT removed. To also remove them:"
    warn "  sudo rm -rf ${DATA_DIR} ${LOG_DIR}"
    warn "  sudo userdel ${SERVICE_USER}"
    ok "Uninstall complete."
    exit 0
}

# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
    parse_args "$@"
    print_banner

    detect_pkg_manager
    detect_distro

    if [ "$DO_UNINSTALL" = true ]; then
        setup_sudo
        check_systemd
        do_uninstall
    fi

    info "Starting Absolute DB v${VERSION} installation..."
    info "Install dir:  ${INSTALL_DIR}"
    info "Prefix:       ${PREFIX}"
    info "Branch:       ${BRANCH}"
    info "Service:      ${DO_SERVICE}"
    echo ""

    check_systemd
    check_selinux
    check_firewalld
    check_disk_space
    check_network
    setup_sudo

    install_prerequisites
    ensure_gcc
    verify_tools
    clone_repository
    build_absdb
    install_binaries
    setup_directories_and_user
    install_service
    verify_install
    print_summary
}

main "$@"
