#!/usr/bin/env bash
# =============================================================================
# onx-check-updates — Query available system updates (dnf check-update)
#
# Purpose:
#   Run `dnf check-update` and emit available package list as JSON.
#   Does NOT install anything — read-only inventory pass.
#
# Input (stdin JSON): {} (no arguments required)
#
# Output (stdout JSON):
#   {
#     "count": 14,
#     "packages": [
#       {"name": "httpd", "current": "2.4.62-1.el9", "available": "2.4.63-1.el9", "size_kb": 1420},
#       ...
#     ],
#     "reboot_required": true|false,
#     "checked_at": "2026-05-15T14:30:00+00:00"
#   }
#
# Exit codes: 0=ok 1=invalid-input 3=execution-fail
#
# NOTE: dnf exits 100 when updates ARE available, 0 when none — both are success.
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=/dev/null
[[ -f "${SCRIPT_DIR}/_lib/common.sh" ]] && source "${SCRIPT_DIR}/_lib/common.sh"

command -v jq >/dev/null 2>&1 || { printf '{"error":"jq required"}\n' >&2; exit 2; }

# Read stdin (we ignore content but consume it so callers' pipes don't break)
cat >/dev/null 2>&1 || true

# ── Run dnf check-update ─────────────────────────────────────────────────────
TMPOUT=$(mktemp /tmp/onx-check-updates-XXXXXX.log)
trap 'rm -f "$TMPOUT"' EXIT

EXIT_CODE=0
dnf check-update --quiet --refresh > "$TMPOUT" 2>&1 || EXIT_CODE=$?

# dnf exits 100 when there ARE updates, 0 when none — both are normal
if [[ "$EXIT_CODE" -ne 0 && "$EXIT_CODE" -ne 100 ]]; then
  TAIL=$(tail -3 "$TMPOUT" | tr '\n' ' ' | sed 's/"/\\"/g')
  printf '{"error":"dnf check-update basarisiz (exit %d): %s","code":3}\n' "$EXIT_CODE" "$TAIL" >&2
  exit 3
fi

# ── Parse package list ───────────────────────────────────────────────────────
# Output format per package row:
#   <name>.<arch>  <version>  <repo>
PACKAGES_JSON="[]"
COUNT=0

if [[ "$EXIT_CODE" -eq 100 ]]; then
  # Strip blank lines and Obsoleting Packages section header
  PKG_ROWS=$(grep -E '^[a-zA-Z0-9]' "$TMPOUT" 2>/dev/null | grep -v '^Obsoleting' | grep -v '^Last metadata' || true)

  # Build JSON array
  PACKAGES_JSON=$(echo "$PKG_ROWS" | head -100 | awk '
    NF >= 3 {
      # name.arch -> name
      split($1, parts, ".")
      name = parts[1]
      available = $2
      printf "{\"name\":\"%s\",\"current\":\"\",\"available\":\"%s\",\"size_kb\":0}\n", name, available
    }
  ' | jq -s . 2>/dev/null || echo "[]")

  COUNT=$(echo "$PACKAGES_JSON" | jq 'length' 2>/dev/null || echo "0")
fi

# ── Reboot required? ─────────────────────────────────────────────────────────
# Multiple signals: /run/reboot-required (Debian-style, sometimes via dnf-plugin),
# or check if kernel/glibc/systemd is in the upgrade list.
REBOOT_REQUIRED=false
if [[ -f /run/reboot-required ]] || [[ -f /var/run/reboot-required ]]; then
  REBOOT_REQUIRED=true
fi

# Also use needs-restarting if available (yum-utils)
if command -v needs-restarting >/dev/null 2>&1; then
  if needs-restarting -r >/dev/null 2>&1; then
    : # rc 0 = no reboot needed
  else
    REBOOT_REQUIRED=true
  fi
fi

# Fallback: check upgrade list for kernel/glibc/systemd packages
if [[ "$REBOOT_REQUIRED" == "false" && "$EXIT_CODE" -eq 100 ]]; then
  if echo "$PKG_ROWS" | grep -qE '^(kernel|glibc|systemd|dbus)\.'; then
    REBOOT_REQUIRED=true
  fi
fi

# ── Emit JSON ────────────────────────────────────────────────────────────────
CHECKED_AT=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00")

jq -n \
  --argjson count "$COUNT" \
  --argjson packages "$PACKAGES_JSON" \
  --argjson reboot "$REBOOT_REQUIRED" \
  --arg checked_at "$CHECKED_AT" \
  '{count: $count, packages: $packages, reboot_required: $reboot, checked_at: $checked_at}'

exit 0
