#!/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-ubuntu.sh
# Copyright 2024–2026 SupportCALL AU & D.H.Maree — SPDX-License-Identifier: BSL-1.1
#
# Supported distros:
#   Ubuntu 18.04 / 20.04 / 22.04 / 24.04
#   Debian 10 (Buster) / 11 (Bullseye) / 12 (Bookworm)
#   Linux Mint 20/21, Pop!_OS 20.04/22.04, elementary OS 6+
#   WSL2 (Ubuntu or Debian image)
#
# Usage:
#   bash install-ubuntu.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

# ---------------------------------------------------------------------------
# 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
    → apt-get install sudo   (as root)
    → Then add yourself: usermod -aG sudo $USER && newgrp sudo

2.  gcc not found / GCC too old (need ≥ 9)
    → sudo apt-get install -y gcc-11
    → sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110
    → Ubuntu 18.04: sudo add-apt-repository ppa:ubuntu-toolchain-r/test
                    sudo apt-get update && sudo apt-get install -y gcc-11

3.  git not found
    → sudo apt-get install -y git

4.  DNS failure / no internet
    → ping -c1 8.8.8.8          # test network
    → cat /etc/resolv.conf       # check DNS
    → sudo systemctl restart systemd-resolved

5.  SSL certificate error (git clone fails)
    → sudo apt-get install -y ca-certificates
    → sudo update-ca-certificates
    → Or temporarily: git -c http.sslVerify=false clone <repo>
    → Proxy users: export https_proxy=http://proxy.corp:3128/

6.  make not found
    → sudo apt-get install -y build-essential make

7.  Permission denied for /usr/local/bin
    → Run with sudo or as root
    → Or use --prefix=$HOME/.local  (then add $HOME/.local/bin to PATH)

8.  Port 5432 already in use
    → sudo ss -tlnp | grep 5432
    → sudo systemctl stop postgresql   # stop conflicting PostgreSQL
    → Or change PG_PORT by editing this script before running

9.  systemd not available (Docker / WSL1)
    → WSL1:  upgrade to WSL2: wsl --set-version Ubuntu 2
    → Docker: use --no-service flag; start manually: absdb-server --daemon
    → Check: [ -d /run/systemd/system ] && echo "systemd running"

10. libm.so.6 not found at runtime
    → sudo apt-get install -y libc6
    → sudo ldconfig

11. Test failures / resource limits
    → ulimit -n 65536           # increase file descriptor limit
    → Check: cat /proc/sys/kernel/perf_event_paranoid  (should be ≤ 2)
    → sudo sysctl -w kernel.perf_event_paranoid=1

12. WSL2 specific notes
    → systemd in WSL2 requires Windows 11 Build 22000+ and WSL 0.67.6+
    → Add to /etc/wsl.conf:  [boot]  systemd=true
    → Then: wsl --shutdown && re-open terminal
    → WSL2 IP changes on restart — use 127.0.0.1 for localhost connections

13. Running as root (Docker containers)
    → The installer supports root — SERVICE_USER will still be created
    → In Docker: use --no-service and start absdb-server manually

14. absdb command not found after install
    → Check PATH: echo $PATH | grep -q /usr/local/bin || echo "MISSING"
    → Add to shell: 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      # check available space
    → Minimum required: 500 MB free
    → du -sh /var/lib/absdb            # check data directory size

16. Proxy environment
    → export http_proxy=http://proxy.corp:3128/
    → export https_proxy=http://proxy.corp:3128/
    → export no_proxy=localhost,127.0.0.1
    → For apt: sudo -E apt-get install ...   (passes env through)
    → 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}  —  Ubuntu / Debian 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 -e ""
    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-ubuntu.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. Install it as root: apt-get install sudo && usermod -aG sudo $USER"
    fi

    # Validate sudo access
    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 sudo group."
    fi

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

# ---------------------------------------------------------------------------
# WSL2 detection
# ---------------------------------------------------------------------------
IS_WSL=false
IS_WSL2=false
detect_wsl() {
    if grep -qiE 'microsoft|wsl' /proc/version 2>/dev/null; then
        IS_WSL=true
        if grep -qi 'WSL2' /proc/version 2>/dev/null || \
           [ -f /proc/sys/fs/binfmt_misc/WSLInterop ]; then
            IS_WSL2=true
            warn "WSL2 detected. systemd may require extra setup (see troubleshooting)."
        else
            warn "WSL1 detected. Recommend upgrading to WSL2 for full systemd support."
            warn "Run from PowerShell: wsl --set-version Ubuntu 2"
            DO_SERVICE=false
        fi
    fi
}

# ---------------------------------------------------------------------------
# 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."
        warn "Service will not be installed. Start manually with: absdb-server --daemon"
        DO_SERVICE=false
    fi
}

# ---------------------------------------------------------------------------
# Distro detection
# ---------------------------------------------------------------------------
DISTRO_ID=""
DISTRO_VERSION=""
DISTRO_CODENAME=""
detect_distro() {
    if [ -f /etc/os-release ]; then
        # shellcheck disable=SC1091
        . /etc/os-release
        DISTRO_ID="${ID:-unknown}"
        DISTRO_VERSION="${VERSION_ID:-0}"
        DISTRO_CODENAME="${VERSION_CODENAME:-}"
        # Normalize derivatives
        case "${ID_LIKE:-}" in
            *debian*|*ubuntu*) DISTRO_ID="ubuntu" ;;
        esac
        case "$DISTRO_ID" in
            linuxmint|pop|elementary|zorin) DISTRO_ID="ubuntu" ;;
            debian) : ;;  # keep as-is
            ubuntu) : ;;
            *) warn "Unrecognised distro '${ID:-unknown}' — treating as Ubuntu-compatible." ; DISTRO_ID="ubuntu" ;;
        esac
    else
        warn "/etc/os-release not found — assuming Debian-compatible."
        DISTRO_ID="ubuntu"
    fi

    info "Distro: ${BOLD}${ID:-$DISTRO_ID} ${DISTRO_VERSION}${NC} (${DISTRO_CODENAME:-n/a})"
}

# ---------------------------------------------------------------------------
# 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 — just warn)
# ---------------------------------------------------------------------------
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/"
    else
        ok "Network connectivity confirmed."
    fi
}

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

    # apt-get may not be available on exotic installs — check
    if ! command -v apt-get >/dev/null 2>&1; then
        die "apt-get not found. This installer requires a Debian/Ubuntu-based system."
    fi

    info "Updating package lists..."
    $SUDO apt-get update -qq || warn "apt-get update failed — continuing with cached lists."

    local pkgs=(
        build-essential
        gcc
        g++
        make
        git
        curl
        wget
        ca-certificates
        libm-dev
        lsb-release
        gnupg
        software-properties-common
        coreutils
        util-linux
        procps
        netcat-openbsd
    )

    info "Installing packages: ${pkgs[*]}"
    $SUDO apt-get install -y --no-install-recommends "${pkgs[@]}" \
        || die "Package installation failed. Check apt output above."

    ok "Base packages installed."
}

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

    local gcc_cmd="gcc"
    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 from toolchain PPA..."

        # Ubuntu 18.04 / 20.04 need the PPA; 22.04+ have gcc-11 natively
        local ubuntu_ver
        ubuntu_ver=$(lsb_release -rs 2>/dev/null | cut -d. -f1 || echo 0)

        if [ "$ubuntu_ver" -lt 22 ] 2>/dev/null; then
            info "Adding ubuntu-toolchain-r/test PPA for GCC 11..."
            $SUDO add-apt-repository -y ppa:ubuntu-toolchain-r/test \
                || die "Failed to add toolchain PPA. Check internet/proxy access."
            $SUDO apt-get update -qq
        fi

        $SUDO apt-get install -y gcc-11 g++-11 \
            || die "Failed to install GCC 11."

        $SUDO update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110 \
            --slave /usr/bin/g++ g++ /usr/bin/g++-11 2>/dev/null || true

        gcc_cmd="gcc-11"
    fi

    # Verify
    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 item for $tool."
        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..."
        # Second attempt: disable SSL (corporate proxy / cert issue)
        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. Consider fixing your CA bundle:"
            warn "  sudo apt-get install -y ca-certificates && sudo update-ca-certificates"
        fi
    fi

    if [ "$clone_ok" = false ]; then
        die "git clone failed. Check internet connection, SSL certs, and proxy settings."
    fi

    ok "Repository cloned to ${INSTALL_DIR}."

    # Verify that the cloned repository matches the expected version
    local repo_ver
    repo_ver=$(grep -o '"[0-9]\+\.[0-9]\+\.[0-9]\+"' "${INSTALL_DIR}/include/adb_types.h" 2>/dev/null | tr -d '"' | head -1)
    if [ -z "$repo_ver" ]; then
        warn "Could not read version from cloned repository — proceeding anyway."
    elif [ "$repo_ver" != "$VERSION" ]; then
        die "Repository version ${repo_ver} does not match expected ${VERSION}. Check BRANCH setting."
    fi
}

# ---------------------------------------------------------------------------
# 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."

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

    # Find and install each binary
    for bin in absdb absdb-server; do
        local src=""
        # Look in common build output locations
        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. (It may not be built on this platform.)"
            continue
        fi

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

    # 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 /usr/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

    # Create directories
    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} — permissions may be incorrect."
        $SUDO chmod 750 "$dir"
        ok "Directory: $dir"
    done
}

# ---------------------------------------------------------------------------
# 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

    $SUDO systemctl daemon-reload \
        || warn "systemctl daemon-reload failed — service may not start automatically."

    $SUDO systemctl enable absdb.service \
        || warn "Failed to enable absdb.service — you can enable it manually."

    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. Check logs:"
        warn "  journalctl -u absdb.service -n 50"
        warn "  cat ${LOG_DIR}/absdb-error.log"
    fi
}

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

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

    # Verify CLI binary
    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. You may need to: source ~/.bashrc"
    fi

    # Verify server binary
    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

    # Check if server is listening (if service was started)
    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 with: sudo systemctl status absdb && journalctl -u absdb -n 30"
            warn "Port conflict: sudo ss -tlnp | grep ${PG_PORT}"
        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
    hdr "  Next Steps"
    echo -e "  ${YLW}1. Open firewall ports for remote access:${NC}"
    echo -e "     ${CYN}sudo ufw allow ${PG_PORT}/tcp    ${NC}${DIM}# PostgreSQL wire protocol${NC}"
    echo -e "     ${CYN}sudo ufw allow ${REST_PORT}/tcp    ${NC}${DIM}# REST API + Web console${NC}"
    echo -e "     ${CYN}sudo ufw allow ${GRPC_PORT}/tcp    ${NC}${DIM}# gRPC / HTTP/2${NC}"
    echo -e "     ${CYN}sudo ufw allow 6379/tcp    ${NC}${DIM}# Redis RESP3 (if enabled)${NC}"
    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

    if [ "$DO_UNINSTALL" = true ]; then
        setup_sudo
        detect_wsl
        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 ""

    detect_distro
    detect_wsl
    check_systemd
    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 "$@"
