#!/usr/bin/env bash

# What this machine is, as JSON: {label, value} pairs in display order.
#
# GNOME's About panel answers "what am I running on" in one screen, and
# fastfetch answers it in more detail; this covers both -- model, OS, kernel,
# uptime, package counts, shell, resolution, processor, memory, swap, disk and
# locale. Rows are ordered roughly the way fastfetch presents them: what the
# system is, then what is installed on it, then the hardware underneath.
#
# Graphics is deliberately absent: GraphicsDevices already enumerates GPUs for
# the vitals readout, and naming them again here would be a second source of
# truth that could disagree with the first. The page joins the two.
#
# Anything unreadable is omitted rather than reported as "Unknown". These are
# facts about hardware, and a row saying "Processor: Unknown" is noise where
# simply not having the row is not.

set -uo pipefail

facts=()

emit() {
    [[ -n "${2:-}" ]] || return 0
    facts+=("$(jq -cn --arg label "$1" --arg value "$2" '{label: $label, value: $value}')")
}

# ── System ───────────────────────────────────────────────────────────────────
if [[ -r /etc/os-release ]]; then
    # Sourced in a subshell so the variables cannot leak into this script.
    os="$( . /etc/os-release 2>/dev/null && printf '%s' "${PRETTY_NAME:-$NAME}" )"
    emit "Operating system" "$os"
fi

# DMI strings are frequently placeholders ("To Be Filled By O.E.M.", "Default
# string"). Those are worse than nothing, so they are filtered out.
dmi() {
    local value
    value="$(cat "/sys/class/dmi/id/$1" 2>/dev/null)" || return 0
    case "$value" in
        ""|"To Be Filled By O.E.M."*|"Default string"|"System Product Name"|"Unknown"|"None") return 0 ;;
    esac
    printf '%s' "$value"
}

vendor="$(dmi sys_vendor)"
product="$(dmi product_name)"
if [[ -n "$vendor" && -n "$product" ]]; then
    emit "Model" "$vendor $product"
else
    emit "Model" "${product:-$vendor}"
fi

emit "Hostname" "$(hostnamectl hostname 2>/dev/null || hostname 2>/dev/null)"
emit "Kernel" "$(uname -r 2>/dev/null)"

# `uptime -p` already reads as prose ("1 week, 23 hours, 5 minutes"); only the
# leading "up " needs removing.
emit "Uptime" "$(uptime -p 2>/dev/null | sed 's/^up //')"

# ── Installed ────────────────────────────────────────────────────────────────
# Counted rather than listed. rpm -qa on a full workstation is a few thousand
# lines and takes a moment, which is part of why this whole helper runs on
# demand rather than at startup.
packages=""
if command -v rpm >/dev/null 2>&1; then
    rpm_count="$(rpm -qa 2>/dev/null | wc -l)"
    [[ "$rpm_count" -gt 0 ]] && packages="$rpm_count rpm"
fi
if command -v flatpak >/dev/null 2>&1; then
    flatpak_count="$(flatpak list --app 2>/dev/null | wc -l)"
    if [[ "$flatpak_count" -gt 0 ]]; then
        [[ -n "$packages" ]] && packages="$packages, "
        packages="$packages$flatpak_count flatpak"
    fi
fi
emit "Packages" "$packages"

# $SHELL is the login shell, which is the one worth reporting -- the shell this
# script happens to run under is an implementation detail of the caller.
if [[ -n "${SHELL:-}" ]]; then
    shell_name="$(basename "$SHELL")"
    shell_version="$("$SHELL" --version 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1)"
    emit "Shell" "${shell_name}${shell_version:+ $shell_version}"
fi

emit "Locale" "${LANG:-}"

case "${XDG_SESSION_TYPE:-}" in
    wayland) emit "Windowing system" "Wayland" ;;
    x11)     emit "Windowing system" "X11" ;;
esac

# ── Hardware ─────────────────────────────────────────────────────────────────
# The focused monitor's actual mode, including the fractional scale, since a
# 4500x3000 panel at 1.5 presents very differently from one at 1.
if command -v hyprctl >/dev/null 2>&1; then
    emit "Resolution" "$(hyprctl -j monitors 2>/dev/null \
        | jq -r 'map(select(.focused)) + . | .[0]
                 | select(. != null)
                 | "\(.width)x\(.height) @ \(.refreshRate | floor)Hz · scale \(.scale)"' 2>/dev/null)"
fi

cpu="$(awk -F': ' '/^model name/ { print $2; exit }' /proc/cpuinfo 2>/dev/null)"
threads="$(nproc 2>/dev/null)"
if [[ -n "$cpu" ]]; then
    # The marketing name usually already says "6-Core", so the thread count is
    # the part that adds information.
    [[ -n "$threads" ]] && cpu="$cpu ($threads threads)"
    emit "Processor" "$cpu"
fi

# Reported as the kernel sees it, which is a little under the sticker figure
# because firmware and integrated graphics reserve some before Linux starts.
#
# Total rather than used: About is not a monitor, and a "12.4 GiB used" figure
# is stale before it finishes drawing. The Home page's vitals readout is where
# live numbers belong.
emit "Memory" "$(awk '/^MemTotal:/ { printf "%.1f GiB", $2 / 1048576 }' /proc/meminfo 2>/dev/null)"

swap="$(awk '/^SwapTotal:/ { if ($2 > 0) printf "%.1f GiB", $2 / 1048576 }' /proc/meminfo 2>/dev/null)"
emit "Swap" "$swap"

# Decimal units with explicit GB/TB labels, matching the Storage page and the
# way drives are actually sold. `df -h` is binary but prints a bare "G", so the
# same drive read 488G here and 523 GB there.
read -r size avail <<<"$(df -B1 --output=size,avail / 2>/dev/null | tail -1)"
if [[ -n "${size:-}" ]]; then
    emit "Disk" "$(awk -v a="$avail" -v s="$size" '
        function human(v,   units, i) {
            split("B KB MB GB TB PB", units, " ")
            i = 1
            while (v >= 1000 && i < 6) { v /= 1000; i++ }
            return sprintf("%.*f %s", (v < 10 && i > 2) ? 1 : 0, v, units[i])
        }
        BEGIN { printf "%s free of %s", human(a), human(s) }')"
fi

printf '[%s]\n' "$(IFS=,; printf '%s' "${facts[*]}")"
