#!/bin/sh
# =============================================================================
# Trident Pre-flight Compatibility Check
#
# Checks if the current system can run Trident and recommends the best
# installation method.
#
# Usage:
#   curl -sSL https://pkg.trident-cache.com/check | sh
#   # or
#   ./check-compatibility.sh
# =============================================================================
set -e

# Minimum GLIBC version for glibc builds (cross-compiled with GLIBC 2.31+)
MIN_GLIBC_MAJOR=2
MIN_GLIBC_MINOR=31

# Minimum disk space in MB
MIN_DISK_MB=100

# Trident default ports
PROXY_PORT=8120
ADMIN_PORT=6085

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
pass() { printf "  \033[32mPASS\033[0m  %s\n" "$1"; }
warn() { printf "  \033[33mWARN\033[0m  %s\n" "$1"; }
fail() { printf "  \033[31mFAIL\033[0m  %s\n" "$1"; ERRORS=$((ERRORS + 1)); }
info() { printf "  \033[36mINFO\033[0m  %s\n" "$1"; }

ERRORS=0
WARNINGS=0

echo ""
echo "==========================================="
echo " Trident Compatibility Check"
echo "==========================================="
echo ""

# ---------------------------------------------------------------------------
# 1. Architecture
# ---------------------------------------------------------------------------
echo "=== Architecture ==="

ARCH=$(uname -m)
case "$ARCH" in
    x86_64|amd64)
        pass "Architecture: x86_64"
        TRIDENT_ARCH="amd64"
        ;;
    aarch64|arm64)
        pass "Architecture: ARM64"
        TRIDENT_ARCH="arm64"
        ;;
    *)
        fail "Unsupported architecture: $ARCH (Trident supports x86_64 and ARM64)"
        TRIDENT_ARCH="unsupported"
        ;;
esac

# ---------------------------------------------------------------------------
# 2. Operating System
# ---------------------------------------------------------------------------
echo ""
echo "=== Operating System ==="

OS=$(uname -s)
case "$OS" in
    Linux)
        pass "OS: Linux"

        # Detect distro
        if [ -f /etc/os-release ]; then
            . /etc/os-release
            DISTRO_ID="${ID}"
            DISTRO_VERSION="${VERSION_ID}"
            DISTRO_NAME="${PRETTY_NAME}"
            pass "Distribution: ${DISTRO_NAME}"
        else
            DISTRO_ID="unknown"
            DISTRO_VERSION=""
            DISTRO_NAME="Unknown Linux"
            warn "Could not detect Linux distribution (/etc/os-release missing)"
        fi
        ;;
    FreeBSD)
        pass "OS: FreeBSD"
        DISTRO_ID="freebsd"
        DISTRO_VERSION=$(freebsd-version 2>/dev/null | cut -d- -f1 || uname -r)
        DISTRO_NAME="FreeBSD ${DISTRO_VERSION}"
        ;;
    Darwin)
        pass "OS: macOS"
        DISTRO_ID="macos"
        DISTRO_VERSION=$(sw_vers -productVersion 2>/dev/null || echo "unknown")
        DISTRO_NAME="macOS ${DISTRO_VERSION}"
        ;;
    *)
        fail "Unsupported OS: $OS (Trident supports Linux, macOS, and FreeBSD)"
        DISTRO_ID="unsupported"
        ;;
esac

# ---------------------------------------------------------------------------
# 3. GLIBC version (Linux only)
# ---------------------------------------------------------------------------
if [ "$OS" = "Linux" ]; then
    echo ""
    echo "=== C Library ==="

    # Check if musl or glibc
    IS_MUSL=false
    if command -v ldd >/dev/null 2>&1; then
        LDD_OUTPUT=$(ldd --version 2>&1 || true)
        if echo "$LDD_OUTPUT" | grep -qi musl; then
            IS_MUSL=true
            pass "C library: musl (static binary recommended)"
        elif echo "$LDD_OUTPUT" | grep -qiE "glibc|gnu libc|GLIBC"; then
            # Extract GLIBC version
            GLIBC_VERSION=$(echo "$LDD_OUTPUT" | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1)
            if [ -n "$GLIBC_VERSION" ]; then
                GLIBC_MAJOR=$(echo "$GLIBC_VERSION" | cut -d. -f1)
                GLIBC_MINOR=$(echo "$GLIBC_VERSION" | cut -d. -f2)

                if [ "$GLIBC_MAJOR" -gt "$MIN_GLIBC_MAJOR" ] || \
                   { [ "$GLIBC_MAJOR" -eq "$MIN_GLIBC_MAJOR" ] && [ "$GLIBC_MINOR" -ge "$MIN_GLIBC_MINOR" ]; }; then
                    pass "GLIBC ${GLIBC_VERSION} (minimum: ${MIN_GLIBC_MAJOR}.${MIN_GLIBC_MINOR})"
                else
                    fail "GLIBC ${GLIBC_VERSION} is too old (minimum: ${MIN_GLIBC_MAJOR}.${MIN_GLIBC_MINOR})"
                    info "Use the musl (static) build instead: trident-linux-${TRIDENT_ARCH}-musl.tar.gz"
                fi
            else
                warn "Could not determine GLIBC version"
            fi
        else
            warn "Unknown C library"
        fi
    elif [ -f /lib/libc.musl-*.so.1 ] 2>/dev/null; then
        IS_MUSL=true
        pass "C library: musl (static binary recommended)"
    else
        warn "Could not detect C library (ldd not found)"
    fi
fi

# ---------------------------------------------------------------------------
# 4. Disk space
# ---------------------------------------------------------------------------
echo ""
echo "=== Disk Space ==="

# Check /usr (binaries) and /var (cache data)
for DIR in /usr /var /etc; do
    if [ -d "$DIR" ]; then
        AVAIL_KB=$(df -k "$DIR" 2>/dev/null | tail -1 | awk '{print $4}')
        if [ -n "$AVAIL_KB" ] && [ "$AVAIL_KB" -gt 0 ] 2>/dev/null; then
            AVAIL_MB=$((AVAIL_KB / 1024))
            if [ "$AVAIL_MB" -ge "$MIN_DISK_MB" ]; then
                pass "${DIR}: ${AVAIL_MB} MB available"
            else
                fail "${DIR}: only ${AVAIL_MB} MB available (minimum: ${MIN_DISK_MB} MB)"
            fi
        fi
    fi
done

# ---------------------------------------------------------------------------
# 5. Port availability
# ---------------------------------------------------------------------------
echo ""
echo "=== Port Availability ==="

check_port() {
    PORT=$1
    NAME=$2
    if command -v ss >/dev/null 2>&1; then
        if ss -tlnp 2>/dev/null | grep -q ":${PORT} "; then
            warn "Port ${PORT} (${NAME}) is already in use"
            WARNINGS=$((WARNINGS + 1))
        else
            pass "Port ${PORT} (${NAME}) is available"
        fi
    elif command -v netstat >/dev/null 2>&1; then
        if netstat -tlnp 2>/dev/null | grep -q ":${PORT} "; then
            warn "Port ${PORT} (${NAME}) is already in use"
            WARNINGS=$((WARNINGS + 1))
        else
            pass "Port ${PORT} (${NAME}) is available"
        fi
    else
        info "Port ${PORT} (${NAME}) — could not check (ss/netstat not found)"
    fi
}

check_port $PROXY_PORT "HTTP proxy"
check_port $ADMIN_PORT "Admin API"

# ---------------------------------------------------------------------------
# 6. Init system
# ---------------------------------------------------------------------------
if [ "$OS" = "Linux" ]; then
    echo ""
    echo "=== Init System ==="

    if command -v systemctl >/dev/null 2>&1 && systemctl --version >/dev/null 2>&1; then
        SYSTEMD_VER=$(systemctl --version 2>/dev/null | head -1 | awk '{print $2}')
        pass "systemd ${SYSTEMD_VER} (service management supported)"
    elif [ -d /etc/init.d ]; then
        info "SysV init detected (manual service setup required)"
    elif command -v rc-service >/dev/null 2>&1; then
        info "OpenRC detected (manual service setup required)"
    else
        info "No supported init system detected (manual startup required)"
    fi
fi

# ---------------------------------------------------------------------------
# 7. Recommended installation method
# ---------------------------------------------------------------------------
echo ""
echo "=== Recommended Install ==="

INSTALL_METHOD=""
INSTALL_CMD=""

case "$DISTRO_ID" in
    debian|ubuntu|linuxmint|pop)
        INSTALL_METHOD=".deb package via APT"
        INSTALL_CMD="curl -sSL https://pkg.trident-cache.com/setup | sudo sh && sudo apt-get install trident"
        ;;
    fedora|rhel|rocky|centos|alma|ol)
        INSTALL_METHOD=".rpm package via YUM/DNF"
        INSTALL_CMD="curl -sSL https://pkg.trident-cache.com/setup | sudo sh && sudo dnf install trident"
        ;;
    opensuse*|sles)
        INSTALL_METHOD=".rpm package via Zypper"
        INSTALL_CMD="curl -sSL https://pkg.trident-cache.com/setup | sudo sh && sudo zypper install trident"
        ;;
    alpine)
        IS_MUSL=true
        INSTALL_METHOD=".apk package"
        INSTALL_CMD="curl -sSL https://pkg.trident-cache.com/setup | sudo sh && sudo apk add trident"
        ;;
    freebsd)
        INSTALL_METHOD=".pkg package"
        INSTALL_CMD="sudo pkg add https://pkg.trident-cache.com/freebsd/amd64/trident-latest.pkg"
        ;;
    macos)
        INSTALL_METHOD="tar.gz binary"
        INSTALL_CMD="curl -sSL https://pkg.trident-cache.com/download/macos-arm64 -o trident.tar.gz && tar xzf trident.tar.gz"
        ;;
    *)
        if [ "$IS_MUSL" = true ]; then
            INSTALL_METHOD="musl static binary"
            INSTALL_CMD="curl -sSL https://pkg.trident-cache.com/download/linux-${TRIDENT_ARCH}-musl -o trident.tar.gz && tar xzf trident.tar.gz"
        else
            INSTALL_METHOD="glibc binary"
            INSTALL_CMD="curl -sSL https://pkg.trident-cache.com/download/linux-${TRIDENT_ARCH} -o trident.tar.gz && tar xzf trident.tar.gz"
        fi
        ;;
esac

info "Recommended: ${INSTALL_METHOD}"
if [ -n "$INSTALL_CMD" ]; then
    echo ""
    printf "  \033[1mInstall command:\033[0m\n"
    printf "  %s\n" "$INSTALL_CMD"
fi

# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
echo ""
echo "==========================================="
TOTAL=$((ERRORS + WARNINGS))
if [ "$ERRORS" -eq 0 ] && [ "$WARNINGS" -eq 0 ]; then
    printf "\033[32mSYSTEM COMPATIBLE — Trident can run on this server\033[0m\n"
elif [ "$ERRORS" -eq 0 ]; then
    printf "\033[33mCOMPATIBLE WITH WARNINGS — %d warning(s)\033[0m\n" "$WARNINGS"
else
    printf "\033[31mINCOMPATIBLE — %d error(s), %d warning(s)\033[0m\n" "$ERRORS" "$WARNINGS"
    echo ""
    echo "Trident may not work correctly on this system."
    echo "Consider using the musl (static) build or a different OS."
fi
echo "==========================================="
echo ""

exit $ERRORS
