```bash
#!/usr/bin/env bash
#
# sysreport.sh - Generate a timestamped system health report.
#
# Usage:
#   ./sysreport.sh          # Human-readable report to stdout and file
#   ./sysreport.sh --json   # JSON report to stdout and file
#
# Dependencies: Standard Linux utilities (bash, awk, grep, sed, cat, date, etc.)
# No external dependencies like jq are required.

set -euo pipefail

# --- Configuration ---
REPORT_DIR="${REPORT_DIR:-.}"
JSON_MODE=false
REPORT_FILE=""

# --- Argument Parsing ---
if [[ "${1:-}" == "--json" ]]; then
    JSON_MODE=true
fi

# --- Helper Functions ---

log_error() {
    echo "ERROR: $*" >&2
}

# Generate ISO-8601 timestamp for filename
get_timestamp() {
    date -u +"%Y-%m-%dT%H:%M:%SZ"
}

# Initialize report file path
init_report_file() {
    local ts
    ts=$(get_timestamp)
    local ext="txt"
    if [[ "$JSON_MODE" == true ]]; then
        ext="json"
    fi
    REPORT_FILE="${REPORT_DIR}/sysreport_${ts}.${ext}"
}

# --- Section Generators (Human Readable) ---

section_header() {
    local title="$1"
    echo "============================================================"
    echo " $title"
    echo "============================================================"
}

get_hostname() {
    hostname
}

get_uptime() {
    uptime -p
}

get_load_average() {
    # /proc/loadavg contains: 1min 5min 15min running/total last_pid
    awk '{print "1min: " $1 ", 5min: " $2 ", 15min: " $3}' /proc/loadavg
}

get_cpu_utilization() {
    # Calculate per-CPU utilization from /proc/stat
    # We take a snapshot, sleep briefly, take another, and calculate delta.
    # For simplicity in a single-pass script without complex background jobs,
    # we use top or mpstat if available, but to avoid deps, we parse /proc/stat twice.
    
    # Snapshot 1
    local cpu1 cpu2
    cpu1=$(grep '^cpu' /proc/stat)
    sleep 0.5
    cpu2=$(grep '^cpu' /proc/stat)

    # Process using awk
    # Format: cpu user nice system idle iowait irq softirq steal guest guest_nice
    # Utilization = 1 - (idle_delta / total_delta)
    
    echo "$cpu1" | awk -v cpu2="$cpu2" '
    BEGIN {
        split(cpu2, arr2, " ");
        # arr2[1] is "cpuX", arr2[2..] are values
    }
    {
        # arr1[1] is "cpuX", arr1[2..] are values
        if ($1 == "cpu") {
            label = "Total"
        } else {
            label = $1
        }
        
        total1 = 0
        for (i=2; i<=NF; i++) total1 += $i
        
        total2 = 0
        idle1 = $5 + $6 # idle + iowait
        idle2 = arr2[5] + arr2[6]
        
        for (i=2; i<=length(arr2); i++) total2 += arr2[i]
        
        total_delta = total2 - total1
        idle_delta = idle2 - idle1
        
        if (total_delta > 0) {
            util = 100 * (1 - (idle_delta / total_delta))
            printf "%-10s: %6.2f%%\n", label, util
        } else {
            printf "%-10s: %6.2f%%\n", label, 0.00
        }
    }'
}

get_memory_usage() {
    # Parse /proc/meminfo
    awk '
    /^MemTotal:/ { total=$2 }
    /^MemFree:/ { free=$2 }
    /^MemAvailable:/ { available=$2 }
    /^Buffers:/ { buffers=$2 }
    /^Cached:/ { cached=$2 }
    /^SwapTotal:/ { swap_total=$2 }
    /^SwapFree:/ { swap_free=$2 }
    END {
        used = total - free - buffers - cached
        if (used < 0) used = total - free # Fallback if cached/buffers logic varies
        
        printf "Memory: %.2f GB / %.2f GB (%.2f%% used)\n", used/1024/1024, total/1024/1024, (used/total)*100
        printf "Swap:   %.2f GB / %.2f GB (%.2f%% used)\n", (swap_total-swap_free)/1024/1024, swap_total/1024/1024, (swap_total>0 ? ((swap_total-swap_free)/swap_total)*100 : 0)
    }' /proc/meminfo
}

get_top_processes() {
    # Top 10 processes by RSS (Resident Set Size)
    # ps aux --sort=-rss | head -n 11
    ps aux --sort=-rss | head -n 11
}

get_disk_usage() {
    # df -h for human readable, exclude tmpfs/devtmpfs if desired, but keep all mounted
    df -h
}

get_network_interfaces() {
    # List interfaces and their IP addresses
    # Using ip command if available, else ifconfig
    if command -v ip &> /dev/null; then
        ip -o addr show | awk '{print $2, $3, $4}' | grep -v 'lo' | grep -v 'inet6' | sort
    elif command -v ifconfig &> /dev/null; then
        ifconfig | grep -E '^[a-z0-9]|inet ' | awk '/^[a-z0-9]/ {iface=$1} /inet / {print iface, $2}' | grep -v '127.0.0.1'
    else
        echo "No network tool found (ip or ifconfig)"
    fi
}

# --- Section Generators (JSON) ---

json_escape() {
    local str="$1"
    # Escape backslashes, quotes, newlines, tabs, carriage returns
    str="${str//\\/\\\\}"
    str="${str//\"/\\\"}"
    str="${str//$'\n'/\\n}"
    str="${str//$'\t'/\\t}"
    str="${str//$'\r'/\\r}"
    echo "$str"
}

json_hostname() {
    echo "\"hostname\": \"$(json_escape "$(get_hostname)")\""
}

json_uptime() {
    echo "\"uptime\": \"$(json_escape "$(get_uptime)")\""
}

json_load_average() {
    local raw
    raw=$(awk '{print $1, $2, $3}' /proc/loadavg)
    local l1 l5 l15
    read -r l1 l5 l15 <<< "$raw"
    echo "\"load_average\": {\"1min\": $l1, \"5min\": $l5, \"15min\": $l15}"
}

json_cpu_utilization() {
    # Reuse the logic from get_cpu_utilization but output JSON array
    local cpu1 cpu2
    cpu1=$(grep '^cpu' /proc/stat)
    sleep 0.5
    cpu2=$(grep '^cpu' /proc/stat)

    echo "$cpu1" | awk -v cpu2="$cpu2" '
    BEGIN {
        split(cpu2, arr2, " ");
        printf "\"cpu_utilization\": ["
        first = 1
    }
    {
        if ($1 == "cpu") {
            label = "total"
        } else {
            label = $1
        }
        
        total1 = 0
        for (i=2; i<=NF; i++) total1 += $i
        
        total2 = 0
        idle1 = $5 + $6
        idle2 = arr2[5] + arr2[6]
        
        for (i=2; i<=length(arr2); i++) total2 += arr2[i]
        
        total_delta = total2 - total1
        idle_delta = idle2 - idle1
        
        if (total_delta > 0) {
            util = 100 * (1 - (idle_delta / total_delta))
        } else {
            util = 0.00
        }
        
        if (!first) printf ","
        printf "{\"cpu\": \"%s\", \"utilization_percent\": %.2f}", label, util
        first = 0
    }
    END {
        printf "]"
    }'
}

json_memory_usage() {
    awk '
    /^MemTotal:/ { total=$2 }
    /^MemFree:/ { free=$2 }
    /^MemAvailable:/ { available=$2 }
    /^Buffers:/ { buffers=$2 }
    /^Cached:/ { cached=$2 }
    /^SwapTotal:/ { swap_total=$2 }
    /^SwapFree:/ { swap_free=$2 }
    END {
        used = total - free - buffers - cached
        if (used < 0) used = total - free
        
        printf "\"memory\": {\n"
        printf "  \"total_kb\": %d,\n", total
        printf "  \"used_kb\": %d,\n", used
        printf "  \"free_kb\": %d,\