#!/usr/bin/env bash

# epc670-versions
# Collects package versions and displays as a grouped table.
# apt and pip packages are read from /etc/epc670/monitored-packages.conf.

VENV_PIP="/opt/venv/epc670/bin/pip"
TOFHAT_UTILS_VERSION_FILE="/usr/share/epc670/epc670-tofhat-utils.version"
PACKAGES_CONF="/etc/epc670/monitored-packages.conf"

# ── DKMS packages to monitor ──────────────────────────────────────────────────
DKMS_PACKAGES=(
    "cam-epc670"
    "clk-si5351"
)

# ── Python packages fallback (used when monitored-packages.conf is absent) ────
PYTHON_PACKAGES_FALLBACK=(
    "epc-tofcam-native"
    "epc-tofcam-toolkit"
)

# Arrays to hold table rows per group: "Name|Version|Status"
STARTER_ROWS=()
EPC_ROWS=()
DKMS_ROWS=()
PYTHON_ROWS=()

# ── Helper: print a table from an array of "Name|Version|Status" rows ──────────
print_table() {
    local TITLE="$1"
    shift
    local ROWS=("$@")

    local COL1=4 COL2=7  # min widths for "Name" and "Version"
    for ROW in "${ROWS[@]}"; do
        IFS='|' read -r NAME VER _ <<< "$ROW"
        [[ ${#NAME} -gt $COL1 ]] && COL1=${#NAME}
        [[ ${#VER}  -gt $COL2 ]] && COL2=${#VER}
    done

    local BORDER
    BORDER=$(printf '+-%*s-+-%*s-+' "-$COL1" "" "-$COL2" "" | tr ' ' '-')

    echo ""
    echo "  $TITLE"
    echo "$BORDER"
    printf '| %-*s | %-*s |\n' "$COL1" "Name" "$COL2" "Version"
    echo "$BORDER"
    for ROW in "${ROWS[@]}"; do
        IFS='|' read -r NAME VER STATUS <<< "$ROW"
        if [[ "$STATUS" == "ok" ]]; then
            printf '| %-*s | %-*s |\n' "$COL1" "$NAME" "$COL2" "$VER"
        else
            printf '| %-*s | %-*s |\n' "$COL1" "$NAME" "$COL2" "N/A  ($STATUS)"
        fi
    done
    echo "$BORDER"
}

# ── Parse monitored-packages.conf ─────────────────────────────────────────────
APT_PACKAGES=()
APT_PACKAGES_OPTIONAL=()
PYTHON_PACKAGES=()
PYTHON_PACKAGES_OPTIONAL=()

if [[ ! -f "$PACKAGES_CONF" ]]; then
    # ── Fallback: scan /usr/share/epc and /usr/share/epc670 .version files ──────
    for DIR in "/usr/share/epc" "/usr/share/epc670"; do
        [[ ! -d "$DIR" ]] && continue
        while IFS= read -r -d '' FILE; do
            NAME=$(basename "$FILE" .version)
            # Skip epc670-tofhat-utils kit and anything listed in DKMS_PACKAGES
            [[ "$NAME" == "epc670-tofhat-utils" ]] && continue
            IS_DKMS=false
            for DKMS_PKG in "${DKMS_PACKAGES[@]}"; do
                [[ "$NAME" == "$DKMS_PKG" ]] && IS_DKMS=true && break
            done
            [[ "$IS_DKMS" == true ]] && continue
            VERSION=$(cat "$FILE" | tr -d '[:space:]')
            [[ -z "$VERSION" ]] && VERSION="(empty)"
            EPC_ROWS+=("$NAME|$VERSION|ok")
        done < <(find "$DIR" -maxdepth 3 -type f -name "*.version" -print0 | sort -z)
    done
    [[ ${#EPC_ROWS[@]} -eq 0 ]] && EPC_ROWS+=("(no .version files found)|—|not found")
else
    while IFS= read -r LINE; do
        LINE="${LINE%%#*}"
        LINE="${LINE//[[:space:]]/}"
        [[ -z "$LINE" ]] && continue

        TYPE="${LINE%%:*}"
        SPEC="${LINE#*:}"

        case "$TYPE" in
            apt)
                if [[ "$SPEC" == *'?' ]]; then
                    APT_PACKAGES_OPTIONAL+=("${SPEC%?}")
                else
                    APT_PACKAGES+=("$SPEC")
                fi
                ;;
            pip)
                if [[ "$SPEC" == *'?' ]]; then
                    PYTHON_PACKAGES_OPTIONAL+=("${SPEC%?}")
                else
                    PYTHON_PACKAGES+=("$SPEC")
                fi
                ;;
        esac
    done < "$PACKAGES_CONF"
fi

# ── Collect epc670-tofhat-utils (top-level, shown first) ───────────────────────
if [[ -f "$TOFHAT_UTILS_VERSION_FILE" ]]; then
    VERSION=$(cat "$TOFHAT_UTILS_VERSION_FILE" | tr -d '[:space:]')
    [[ -z "$VERSION" ]] && VERSION="(empty)"
    STARTER_ROWS+=("epc670-tofhat-utils|$VERSION|ok")
else
    STARTER_ROWS+=("epc670-tofhat-utils|—|not found")
fi

# ── Collect epc packages from dpkg (apt packages in monitored-packages.conf) ──
for PKG in "${APT_PACKAGES[@]}"; do
    VERSION=$(dpkg-query -W -f='${Version}' "$PKG" 2>/dev/null || true)
    if [[ -n "$VERSION" ]]; then
        EPC_ROWS+=("$PKG|$VERSION|ok")
    else
        EPC_ROWS+=("$PKG|—|not found")
    fi
done

for PKG in "${APT_PACKAGES_OPTIONAL[@]}"; do
    VERSION=$(dpkg-query -W -f='${Version}' "$PKG" 2>/dev/null || true)
    if [[ -n "$VERSION" ]]; then
        EPC_ROWS+=("$PKG|$VERSION|ok")
    else
        EPC_ROWS+=("$PKG|—|optional")
    fi
done

[[ ${#EPC_ROWS[@]} -eq 0 ]] && EPC_ROWS+=("(no apt packages configured)|—|not found")

# ── Collect epc670 dkms packages ─────────────────────────────────────────────
for PKG in "${DKMS_PACKAGES[@]}"; do
    FILE="/usr/share/epc/${PKG}.version"
    if [[ -f "$FILE" ]]; then
        VERSION=$(cat "$FILE" | tr -d '[:space:]')
        [[ -z "$VERSION" ]] && VERSION="(empty)"
        DKMS_ROWS+=("$PKG|$VERSION|ok")
    else
        DKMS_ROWS+=("$PKG|—|not found")
    fi
done

# ── Collect Python packages ───────────────────────────────────────────────────
# Use fallback list if monitored-packages.conf was not available
if [[ ${#PYTHON_PACKAGES[@]} -eq 0 && ${#PYTHON_PACKAGES_OPTIONAL[@]} -eq 0 ]]; then
    PYTHON_PACKAGES=("${PYTHON_PACKAGES_FALLBACK[@]}")
fi

if [[ ! -x "$VENV_PIP" ]]; then
    for SPEC in "${PYTHON_PACKAGES[@]}" "${PYTHON_PACKAGES_OPTIONAL[@]}"; do
        PKG_NAME="${SPEC%%[><=]*}"
        PKG_NAME="${PKG_NAME%%\[*}"
        PYTHON_ROWS+=("$PKG_NAME|—|venv not found")
    done
else
    for SPEC in "${PYTHON_PACKAGES[@]}"; do
        PKG_NAME="${SPEC%%[><=]*}"
        PKG_NAME="${PKG_NAME%%\[*}"
        VERSION=$("$VENV_PIP" show "$PKG_NAME" 2>/dev/null | grep -i "^Version:" | awk '{print $2}')
        if [[ -n "$VERSION" ]]; then
            PYTHON_ROWS+=("$PKG_NAME|$VERSION|ok")
        else
            PYTHON_ROWS+=("$PKG_NAME|—|not found")
        fi
    done

    for SPEC in "${PYTHON_PACKAGES_OPTIONAL[@]}"; do
        PKG_NAME="${SPEC%%[><=]*}"
        PKG_NAME="${PKG_NAME%%\[*}"
        VERSION=$("$VENV_PIP" show "$PKG_NAME" 2>/dev/null | grep -i "^Version:" | awk '{print $2}')
        if [[ -n "$VERSION" ]]; then
            PYTHON_ROWS+=("$PKG_NAME|$VERSION|ok")
        else
            PYTHON_ROWS+=("$PKG_NAME|—|optional")
        fi
    done
fi

# ── Print all tables ──────────────────────────────────────────────────────────
REPORT_TITLE=" epc Component Version Report "
REPORT_BORDER=$(printf "%${#REPORT_TITLE}s" | tr " " "=")
echo "$REPORT_BORDER"
echo "$REPORT_TITLE"
echo "$REPORT_BORDER"

print_table "epc670 ToF HAT+ utils"               "${STARTER_ROWS[@]}"
print_table "epc packages"                        "${EPC_ROWS[@]}"
print_table "epc670 dkms packages"                "${DKMS_ROWS[@]}"
print_table "Python packages  (/opt/venv/epc670)" "${PYTHON_ROWS[@]}"

echo ""
