#!/bin/bash
# ============================================================================
# curve-diag — Curve Reality CB302B Diagnostics
# Version: 0.1.0
# ============================================================================

VERSION="0.2.0"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

ok()   { printf "  ${GREEN}✓${NC} %s\n" "$*"; }
fail() { printf "  ${RED}✗${NC} %s\n" "$*"; }
warn() { printf "  ${YELLOW}⚠${NC} %s\n" "$*"; }
info() { printf "  ${CYAN}·${NC} %s\n" "$*"; }

section() { printf "\n${BOLD}%s${NC}\n" "$*"; }

ISSUES=0
WARNINGS=0

# ── Platform ───────────────────────────────────────────────────────────────

section "Platform"
info "curve-diag v${VERSION}"
info "Kernel: $(uname -r)"
info "Arch: $(uname -m)"

if [ "$(uname -m)" != "aarch64" ]; then
    fail "Not aarch64 — Curve requires ARM64"
    ISSUES=$((ISSUES + 1))
else
    ok "Architecture: aarch64"
fi

KERNEL=$(uname -r)
if [[ "$KERNEL" == *tegra* ]]; then
    ok "Tegra kernel detected: ${KERNEL}"
else
    warn "Non-Tegra kernel: ${KERNEL} — Curve extras may not work correctly"
    WARNINGS=$((WARNINGS + 1))
fi

# ── Installed Files ────────────────────────────────────────────────────────

section "Installed Files"

MODDIR="/lib/modules/${KERNEL}/extra/curve"

check_file() {
    local path="$1" label="$2"
    if [ -f "$path" ]; then
        ok "${label}: ${path}"
    else
        fail "${label}: ${path} — MISSING"
        ISSUES=$((ISSUES + 1))
    fi
}

check_file "${MODDIR}/bmi270_core.ko"      "BMI270 core module"
check_file "${MODDIR}/bmi270_i2c.ko"       "BMI270 I2C module"
check_file "${MODDIR}/bmc150_magn.ko"      "BMM150 core module"
check_file "${MODDIR}/bmc150_magn_i2c.ko"  "BMM150 I2C module"
check_file "/lib/firmware/bmi270-init-data.fw" "BMI270 firmware"

if [ -f "/usr/lib/curve-extras/curve-extras.sh" ]; then
    ok "Service script: /usr/lib/curve-extras/curve-extras.sh"
else
    fail "Service script: MISSING"
    ISSUES=$((ISSUES + 1))
fi

if [ -f "/etc/systemd/system/curve-extras.service" ]; then
    ok "Systemd unit: /etc/systemd/system/curve-extras.service"
else
    fail "Systemd unit: MISSING"
    ISSUES=$((ISSUES + 1))
fi

# ── Modules ────────────────────────────────────────────────────────────────

section "Loaded Modules"

check_module() {
    local mod="$1"
    local mod_under="${mod//-/_}"
    if lsmod | grep -q "^${mod_under}"; then
        ok "${mod} loaded"
    else
        fail "${mod} NOT loaded"
        ISSUES=$((ISSUES + 1))
    fi
}

check_module kfifo_buf
check_module industrialio_triggered_buffer
check_module bmi270_core
check_module bmi270_i2c
check_module bmc150_magn
check_module bmc150_magn_i2c
check_module sbs_battery

# ── I2C Buses ──────────────────────────────────────────────────────────────

section "I2C Buses"

check_bus() {
    local bus="$1" label="$2"
    if [ -d "/sys/bus/i2c/devices/i2c-${bus}" ]; then
        ok "Bus ${bus}: present (${label})"
    else
        fail "Bus ${bus}: MISSING (${label})"
        ISSUES=$((ISSUES + 1))
    fi
}

check_bus 7 "c250000.i2c — IMU"
check_bus 1 "c240000.i2c — Battery"

# ── I2C Devices ────────────────────────────────────────────────────────────

section "I2C Devices"

check_i2c_device() {
    local bus="$1" addr="$2" label="$3"
    local addr_fmt
    addr_fmt=$(printf '%04x' "$addr")
    if [ -d "/sys/bus/i2c/devices/${bus}-${addr_fmt}" ]; then
        ok "${label}: i2c-${bus} @ 0x$(printf '%02x' "$addr") — instantiated"
    else
        fail "${label}: i2c-${bus} @ 0x$(printf '%02x' "$addr") — NOT instantiated"
        ISSUES=$((ISSUES + 1))
    fi
}

check_i2c_device 7 0x68 "BMI270 (accel+gyro)"
check_i2c_device 7 0x10 "BMM150 (magnetometer)"
check_i2c_device 1 0x0b "BQ40Z50 (battery)"

# ── IMU (IIO) ──────────────────────────────────────────────────────────────

section "IMU — IIO Devices"

found_accel=false
found_gyro=false
found_mag=false

for dev in /sys/bus/iio/devices/iio:device*/; do
    [ -d "$dev" ] || continue
    devname=$(basename "$dev")
    name=$(cat "${dev}name" 2>/dev/null || echo "(unnamed)")

    if [ -f "${dev}in_accel_x_raw" ]; then
        found_accel=true
        scale=$(cat "${dev}in_accel_x_scale" 2>/dev/null || echo "?")
        val=$(cat "${dev}in_accel_z_raw" 2>/dev/null || echo "?")
        ok "Accelerometer: ${devname} [${name}] — Z raw=${val}, scale=${scale}"
    fi

    if [ -f "${dev}in_anglvel_x_raw" ]; then
        found_gyro=true
        scale=$(cat "${dev}in_anglvel_x_scale" 2>/dev/null || echo "?")
        ok "Gyroscope: ${devname} [${name}] — scale=${scale}"
    fi

    if [ -f "${dev}in_magn_x_raw" ]; then
        found_mag=true
        x=$(cat "${dev}in_magn_x_raw" 2>/dev/null || echo "?")
        y=$(cat "${dev}in_magn_y_raw" 2>/dev/null || echo "?")
        z=$(cat "${dev}in_magn_z_raw" 2>/dev/null || echo "?")
        ok "Magnetometer: ${devname} [${name}] — X=${x} Y=${y} Z=${z}"
    fi
done

$found_accel || { fail "Accelerometer: no IIO device with accel channels"; ISSUES=$((ISSUES + 1)); }
$found_gyro  || { fail "Gyroscope: no IIO device with gyro channels"; ISSUES=$((ISSUES + 1)); }
$found_mag   || { fail "Magnetometer: no IIO device with magn channels"; ISSUES=$((ISSUES + 1)); }

# ── Battery ────────────────────────────────────────────────────────────────

section "Battery — Power Supply"

found_battery=false
for ps in /sys/class/power_supply/*/; do
    [ -d "$ps" ] || continue
    type=$(cat "${ps}type" 2>/dev/null) || continue
    if [ "$type" = "Battery" ]; then
        found_battery=true
        psname=$(basename "$ps")
        capacity=$(cat "${ps}capacity" 2>/dev/null || echo "?")
        voltage=$(cat "${ps}voltage_now" 2>/dev/null || echo "?")
        status=$(cat "${ps}status" 2>/dev/null || echo "?")
        if [ "$voltage" != "?" ]; then
            voltage_v=$(echo "scale=3; $voltage / 1000000" | bc 2>/dev/null || echo "${voltage}µV")
        else
            voltage_v="?"
        fi
        ok "Battery: ${psname} — ${capacity}%, ${voltage_v}V, ${status}"
    fi
done

if ! $found_battery; then
    fail "Battery: no power_supply with type=Battery found"
    ISSUES=$((ISSUES + 1))
fi

# ── Service Status ─────────────────────────────────────────────────────────

section "Service"

if systemctl is-enabled curve-extras.service >/dev/null 2>&1; then
    ok "curve-extras.service: enabled"
else
    warn "curve-extras.service: not enabled"
    WARNINGS=$((WARNINGS + 1))
fi

if systemctl is-active curve-extras.service >/dev/null 2>&1; then
    ok "curve-extras.service: active (ran successfully)"
else
    svc_state=$(systemctl is-active curve-extras.service 2>/dev/null || echo "unknown")
    if [ "$svc_state" = "failed" ]; then
        fail "curve-extras.service: FAILED"
        ISSUES=$((ISSUES + 1))
    else
        warn "curve-extras.service: ${svc_state}"
        WARNINGS=$((WARNINGS + 1))
    fi
fi

# ── Recent logs ────────────────────────────────────────────────────────────

section "Recent Service Logs"
if journalctl -u curve-extras -n 10 --no-pager 2>/dev/null | grep -q "curve-extras"; then
    journalctl -u curve-extras -n 10 --no-pager 2>/dev/null | while IFS= read -r line; do
        info "$line"
    done
else
    info "(no logs yet — service may not have run)"
fi

# ── Summary ────────────────────────────────────────────────────────────────

section "Summary"
if [ "$ISSUES" -eq 0 ] && [ "$WARNINGS" -eq 0 ]; then
    printf "  ${GREEN}${BOLD}All checks passed ✓${NC}\n"
elif [ "$ISSUES" -eq 0 ]; then
    printf "  ${YELLOW}${BOLD}${WARNINGS} warning(s), no errors${NC}\n"
else
    printf "  ${RED}${BOLD}${ISSUES} issue(s)${NC}"
    [ "$WARNINGS" -gt 0 ] && printf ", ${YELLOW}${WARNINGS} warning(s)${NC}"
    printf "\n"
    printf "\n  Suggested actions:\n"
    printf "    sudo systemctl restart curve-extras\n"
    printf "    journalctl -u curve-extras --no-pager\n"
fi

echo ""
exit $ISSUES
