#!/bin/sh

# ==============================================================================
# OpenWrt 24.10.4 系统信息看板脚本 (sysinfo.sh)
# ==============================================================================
# 功能: 自动安装依赖并展示CPU、内存、硬盘、温度、网络流量、Docker状态、系统运行时间
#       以及PPPoE宽带连接时长等关键设备信息。
# ==============================================================================

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color

# 绘制分割线
draw_separator() {
    echo -e "${CYAN}========================================================================${NC}"
}

# 绘制子标题
draw_subtitle() {
    echo -e "${BLUE}>>> $1${NC}"
}

# 格式化字节数 (Bytes -> KB/MB/GB/TB)
format_bytes() {
    local bytes=$1
    if [ -z "$bytes" ] || [ "$bytes" -eq 0 ]; then
        echo "0 B"
        return
    fi
    awk -v b="$bytes" 'BEGIN {
        if (b >= 1099511627776) { printf "%.2f TB", b/1099511627776 }
        else if (b >= 1073741824) { printf "%.2f GB", b/1073741824 }
        else if (b >= 1048576) { printf "%.2f MB", b/1048576 }
        else if (b >= 1024) { printf "%.2f KB", b/1024 }
        else { printf "%d B", b }
    }'
}

# 格式化时长 (秒 -> 天/时/分/秒)
format_duration() {
    local seconds=$1
    if [ -z "$seconds" ] || [ "$seconds" -eq 0 ]; then
        echo "0 秒"
        return
    fi
    local days=$((seconds / 86400))
    local hours=$(( (seconds % 86400) / 3600 ))
    local mins=$(( (seconds % 3600) / 60 ))
    local secs=$(( seconds % 60 ))
    
    local result=""
    [ "$days" -gt 0 ] && result="${days}天 "
    [ "$hours" -gt 0 ] || [ "$days" -gt 0 ] && result="${result}${hours}小时 "
    [ "$mins" -gt 0 ] || [ "$hours" -gt 0 ] || [ "$days" -gt 0 ] && result="${result}${mins}分 "
    result="${result}${secs}秒"
    echo "$result"
}

# 绘制简易进度条
draw_progress_bar() {
    local percentage=$1
    local width=20
    local filled=$(( percentage * width / 100 ))
    local empty=$(( width - filled ))
    local bar=""
    
    local i=0
    while [ $i -lt $filled ]; do
        bar="${bar}#"
        i=$((i + 1))
    done
    
    i=0
    while [ $i -lt $empty ]; do
        bar="${bar}-"
        i=$((i + 1))
    done
    
    local color=$GREEN
    if [ "$percentage" -ge 90 ]; then
        color=$RED
    elif [ "$percentage" -ge 75 ]; then
        color=$YELLOW
    fi
    
    echo -e "${color}[${bar}] ${percentage}%${NC}"
}

# 1. 自动更新 opkg 并安装必要插件
install_dependencies() {
    draw_separator
    echo -e "${YELLOW}正在检查并安装必要插件及工具...${NC}"
    
    # 检查是否安装了 lm-sensors
    local has_sensors=0
    if command -v sensors >/dev/null 2>&1; then
        has_sensors=1
    fi
    
    # 我们也可以在此添加其他需要的轻量工具，如 ubus, jsonfilter (OpenWrt自带)
    if [ "$has_sensors" -eq 0 ]; then
        echo -e "${YELLOW}未检测到 lm-sensors，正在更新软件源并进行安装...${NC}"
        opkg update
        if [ $? -eq 0 ]; then
            opkg install lm-sensors
            if [ $? -eq 0 ]; then
                echo -e "${GREEN}lm-sensors 安装成功！${NC}"
            else
                echo -e "${RED}lm-sensors 安装失败，请检查网络或软件源设置。${NC}"
            fi
        else
            echo -e "${RED}opkg 软件源更新失败，无法安装 lm-sensors，脚本将使用系统内核接口获取温度。${NC}"
        fi
    else
        echo -e "${GREEN}lm-sensors 已安装，跳过安装步骤。${NC}"
    fi
}

# 2. 系统基本信息及已运行时间
get_system_uptime() {
    draw_subtitle "系统基本运行状态"
    
    # 主机名
    local hostname=$(cat /proc/sys/kernel/hostname)
    # 系统版本
    local sys_ver=$(cat /etc/openwrt_release | grep DISTRIB_DESCRIPTION | cut -d"'" -f2)
    [ -z "$sys_ver" ] && sys_ver=$(cat /etc/banner | head -n 3 | tail -n 1 | sed 's/^[ \t]*//')
    # 内核版本
    local kernel_ver=$(uname -r)
    
    # 系统运行时间
    local uptime_raw=$(cat /proc/uptime | awk '{print $1}')
    local uptime_secs=${uptime_raw%.*}
    local uptime_formatted=$(format_duration "$uptime_secs")
    
    echo -e "设备主机名称: ${WHITE}${hostname}${NC}"
    echo -e "固件系统版本: ${WHITE}${sys_ver:-OpenWrt}${NC}"
    echo -e "系统内核版本: ${WHITE}${kernel_ver}${NC}"
    echo -e "系统运行时间: ${GREEN}${uptime_formatted}${NC}"
}

# 3. CPU 状态
get_cpu_info() {
    draw_subtitle "CPU 状态信息"
    
    # 获取 CPU 型号
    local cpu_model=$(grep -m 1 "model name" /proc/cpuinfo | cut -d: -f2 | sed 's/^[ \t]*//')
    [ -z "$cpu_model" ] && cpu_model=$(grep -m 1 "cpu model" /proc/cpuinfo | cut -d: -f2 | sed 's/^[ \t]*//')
    [ -z "$cpu_model" ] && cpu_model=$(grep -m 1 "system type" /proc/cpuinfo | cut -d: -f2 | sed 's/^[ \t]*//')
    [ -z "$cpu_model" ] && cpu_model=$(uname -m)
    
    # 核心数
    local cpu_cores=$(grep -c '^processor' /proc/cpuinfo)
    
    # 负载状况
    local loadavg=$(cat /proc/loadavg | awk '{print $1" "$2" "$3}')
    
    # 计算瞬时 CPU 使用率 (1秒采样)
    read -r cpu user nice system idle iowait irq softirq steal guest guest_nice < /proc/stat
    local prev_idle=$((idle + iowait))
    local prev_non_idle=$((user + nice + system + irq + softirq + steal))
    local prev_total=$((prev_idle + prev_non_idle))

    sleep 1

    read -r cpu user nice system idle iowait irq softirq steal guest guest_nice < /proc/stat
    local curr_idle=$((idle + iowait))
    local curr_non_idle=$((user + nice + system + irq + softirq + steal))
    local curr_total=$((curr_idle + curr_non_idle))

    local total_diff=$((curr_total - prev_total))
    local idle_diff=$((curr_idle - prev_idle))

    local cpu_usage_pct=0
    if [ "$total_diff" -ne 0 ]; then
        cpu_usage_pct=$(((total_diff - idle_diff) * 100 / total_diff))
    fi
    
    echo -e "CPU 型号架构: ${WHITE}${cpu_model} (${cpu_cores}核)${NC}"
    echo -e "CPU 负载情况: ${WHITE}${loadavg}${NC} (1分/5分/15分)"
    echo -ne "CPU 使用率  : "
    draw_progress_bar "$cpu_usage_pct"
}

# 4. 内存状态
get_memory_info() {
    draw_subtitle "内存 (RAM) 状态信息"
    
    # 从 /proc/meminfo 中获取，确保高兼容性
    local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
    local mem_free=$(grep MemFree /proc/meminfo | awk '{print $2}')
    local mem_cached=$(grep ^Cached /proc/meminfo | awk '{print $2}')
    local mem_buffers=$(grep Buffers /proc/meminfo | awk '{print $2}')
    local mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
    
    if [ -z "$mem_avail" ]; then
        # 兼容旧版本内核
        mem_avail=$((mem_free + mem_cached + mem_buffers))
    fi
    
    local mem_used=$((mem_total - mem_avail))
    
    # 转换为字节并进行格式化输出
    local mem_total_bytes=$((mem_total * 1024))
    local mem_used_bytes=$((mem_used * 1024))
    local mem_avail_bytes=$((mem_avail * 1024))
    
    local mem_usage_pct=0
    if [ "$mem_total" -gt 0 ]; then
        mem_usage_pct=$((mem_used * 100 / mem_total))
    fi
    
    echo -e "内存总容量: $(format_bytes $mem_total_bytes)"
    echo -e "内存已使用: $(format_bytes $mem_used_bytes)"
    echo -e "内存可用量: $(format_bytes $mem_avail_bytes)"
    echo -ne "内存使用率: "
    draw_progress_bar "$mem_usage_pct"
}

# 5. 硬盘/存储空间状态
get_disk_info() {
    draw_subtitle "硬盘/存储空间状态 (DF)"
    
    # 打印表头
    printf "%-22s %-8s %-8s %-8s %-6s %-15s\n" "文件系统" "总大小" "已用" "可用" "已用%" "挂载点"
    
    # 过滤出主流和关键的挂载点进行展示
    df -h | grep -E '^/dev/|^tmpfs|^overlay' | while read -r line; do
        local fs=$(echo "$line" | awk '{print $1}')
        local size=$(echo "$line" | awk '{print $2}')
        local used=$(echo "$line" | awk '{print $3}')
        local avail=$(echo "$line" | awk '{print $4}')
        local percent=$(echo "$line" | awk '{print $5}')
        local mnt=$(echo "$line" | awk '{print $6}')
        
        # 截断过长的主机名/文件系统名以保持格式对齐
        if [ ${#fs} -gt 21 ]; then
            fs="${fs:0:18}..."
        fi
        
        printf "%-22s %-8s %-8s %-8s %-6s %-15s\n" "$fs" "$size" "$used" "$avail" "$percent" "$mnt"
    done
}

# 6. 设备温度获取
get_temperature_info() {
    draw_subtitle "设备温度监控"
    
    local temp_found=0
    
    # 1. 尝试使用安装好的 lm-sensors
    if command -v sensors >/dev/null 2>&1; then
        local sensors_data=$(sensors 2>/dev/null | grep -E '^[a-zA-Z0-9].*:' | grep -E 'temp|Core|Package')
        if [ -n "$sensors_data" ]; then
            echo -e "${YELLOW}[lm-sensors 传感器读数]:${NC}"
            echo "$sensors_data" | while read -r line; do
                echo -e "  $line"
            done
            temp_found=1
        fi
    fi
    
    # 2. 从系统 thermal_zone 获取 (SoC 芯片内置温度传感器)
    local thermal_zones=""
    for zone in /sys/class/thermal/thermal_zone*; do
        if [ -d "$zone" ]; then
            local type=$(cat "$zone/type" 2>/dev/null || echo "未知")
            local temp_raw=$(cat "$zone/temp" 2>/dev/null)
            if [ -n "$temp_raw" ] && [ "$temp_raw" -ne 0 ]; then
                local temp_c=$(awk "BEGIN {printf \"%.1f\", $temp_raw/1000}")
                echo -e "内核热区温度 (${WHITE}${type}${NC}): ${YELLOW}${temp_c} °C${NC}"
                temp_found=1
            fi
        fi
    done
    
    # 3. 从 hwmon 设备中获取 (如主板、网络芯片温度)
    for hwmon in /sys/class/hwmon/hwmon*/temp*_input; do
        if [ -f "$hwmon" ]; then
            local dir=$(dirname "$hwmon")
            local name=$(cat "$dir/name" 2>/dev/null || echo "hwmon")
            
            # 找到对应的label
            local label_file="${hwmon%_input}_label"
            local label=""
            if [ -f "$label_file" ]; then
                label=$(cat "$label_file" 2>/dev/null)
            fi
            [ -z "$label" ] && label=$(basename "$hwmon" | cut -d_ -f1)
            
            local temp_raw=$(cat "$hwmon" 2>/dev/null)
            if [ -n "$temp_raw" ] && [ "$temp_raw" -ne 0 ]; then
                local temp_c=$(awk "BEGIN {printf \"%.1f\", $temp_raw/1000}")
                echo -e "硬件芯片温度 (${WHITE}${name} - ${label}${NC}): ${YELLOW}${temp_c} °C${NC}"
                temp_found=1
            fi
        fi
    done
    
    if [ "$temp_found" -eq 0 ]; then
        echo -e "${RED}未检测到可用的温度传感器或设备不支持温度读取。${NC}"
    fi
}

# 7. 网络接口IP地址和流量
get_network_info() {
    draw_subtitle "网络接口 IP 地址及已交换流量"
    
    printf "%-12s %-6s %-18s %-12s %-12s\n" "网络接口" "状态" "IPv4 / IPv6 地址" "接收流量 (RX)" "发送流量 (TX)"
    
    for dev in $(ls /sys/class/net/); do
        # 排除本地环回
        [ "$dev" = "lo" ] && continue
        
        # 接口状态 (UP / DOWN)
        local operstate=$(cat "/sys/class/net/$dev/operstate" 2>/dev/null)
        local status_color=$RED
        [ "$operstate" = "up" ] && status_color=$GREEN
        
        # 流量数据 (Bytes)
        local rx_bytes=$(cat "/sys/class/net/$dev/statistics/rx_bytes" 2>/dev/null || echo 0)
        local tx_bytes=$(cat "/sys/class/net/$dev/statistics/tx_bytes" 2>/dev/null || echo 0)
        
        local rx_readable=$(format_bytes "$rx_bytes")
        local tx_readable=$(format_bytes "$tx_bytes")
        
        # 获取首个 IPv4 地址
        local ipv4_addr=$(ip -4 addr show dev "$dev" 2>/dev/null | grep inet | awk '{print $2}' | head -n 1)
        # 获取首个非本地链路本地的 IPv6 地址
        local ipv6_addr=$(ip -6 addr show dev "$dev" 2>/dev/null | grep inet6 | grep -v 'fe80::' | awk '{print $2}' | head -n 1)
        
        local ip_show="--"
        if [ -n "$ipv4_addr" ]; then
            ip_show="$ipv4_addr"
        elif [ -n "$ipv6_addr" ]; then
            ip_show="${ipv6_addr:0:15}..." # 截短过长的IPv6以避免格式错乱
        fi
        
        printf "%-12s ${status_color}%-6s${NC} %-18s %-12s %-12s\n" "$dev" "$operstate" "$ip_show" "$rx_readable" "$tx_readable"
        
        # 如果同时有 IPv4 和 IPv6 且前面只印了一个，第二行可以缩进补充展示另一个
        if [ -n "$ipv4_addr" ] && [ -n "$ipv6_addr" ]; then
            printf "%-12s %-6s ${WHITE}%-18s${NC} %-12s %-12s\n" "" "" "v6: ${ipv6_addr}" "" ""
        fi
    done
}

# 8. PPPoE 接口已连接时间
get_pppoe_uptime() {
    draw_subtitle "PPPoE 宽带连接时间"
    
    local pppoe_found=0
    
    # 查找所有的网络接口定义
    for iface in $(uci show network | grep '=interface' | cut -d. -f2 | cut -d= -f1); do
        local proto=$(uci -q get network."$iface".proto)
        
        if [ "$proto" = "pppoe" ]; then
            pppoe_found=1
            # 获取该接口的实时状态
            local status_json=$(ubus call network.interface."$iface" status 2>/dev/null)
            if [ -n "$status_json" ]; then
                local is_up=$(echo "$status_json" | jsonfilter -e '@.up')
                local device=$(echo "$status_json" | jsonfilter -e '@.l3_device')
                
                if [ "$is_up" = "true" ]; then
                    local uptime_secs=$(echo "$status_json" | jsonfilter -e '@.uptime')
                    if [ -n "$uptime_secs" ] && [ "$uptime_secs" -gt 0 ]; then
                        local pppoe_uptime_formatted=$(format_duration "$uptime_secs")
                        echo -e "PPPoE 接口: ${GREEN}${iface}${NC} (物理网卡: ${WHITE}${device:-pppoe-${iface}}${NC})"
                        echo -e "宽带连接状态: ${GREEN}已连接${NC}"
                        echo -e "持续连接时长: ${GREEN}${pppoe_uptime_formatted}${NC}"
                    else
                        echo -e "PPPoE 接口: ${GREEN}${iface}${NC}"
                        echo -e "宽带连接状态: ${GREEN}已连接${NC}，但是系统未返回有效连接时间。"
                    fi
                else
                    echo -e "PPPoE 接口: ${YELLOW}${iface}${NC}"
                    echo -e "宽带连接状态: ${RED}未连接 / 拨号中${NC}"
                fi
            else
                echo -e "PPPoE 接口: ${YELLOW}${iface}${NC} (未能通过 ubus 获取到其网络状态)"
            fi
        fi
    done
    
    if [ "$pppoe_found" -eq 0 ]; then
        echo -e "${YELLOW}未在系统的网络配置文件 (UCI) 中检测到使用 PPPoE 拨号协议的接口。${NC}"
    fi
}

# 9. Docker 容器状态展示
get_docker_status() {
    draw_subtitle "Docker 容器状态展示"
    
    if command -v docker >/dev/null 2>&1; then
        # 检查 docker daemon 是否能连通
        if docker info >/dev/null 2>&1; then
            # 统计总数、运行中、暂停、停止的容器
            local total_containers=$(docker ps -a -q | wc -l)
            local running_containers=$(docker ps -q | wc -l)
            
            echo -e "Docker 服务状态: ${GREEN}运行中 (Active)${NC}"
            echo -e "容器数量总计: ${WHITE}${total_containers}${NC} 个 (其中 ${GREEN}${running_containers}${NC} 个正在运行)"
            echo ""
            
            if [ "$total_containers" -gt 0 ]; then
                # 自定义格式输出表格
                docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | while read -r line; do
                    # 给运行中的容器行标记绿色，给退出的行标记红色
                    if echo "$line" | grep -q "Up"; then
                        echo -e "${GREEN}${line}${NC}"
                    elif echo "$line" | grep -q "Exited"; then
                        echo -e "${RED}${line}${NC}"
                    else
                        echo -e "${WHITE}${line}${NC}"
                    fi
                done
            else
                echo -e "${YELLOW}暂无任何 Docker 容器。${NC}"
            fi
        else
            echo -e "Docker 服务状态: ${RED}已安装但 Daemon 未启动 (Could not connect to Docker daemon)${NC}"
        fi
    else
        echo -e "Docker 服务状态: ${YELLOW}未安装 Docker${NC} (未检测到 docker 命令行客户端)"
    fi
}

# ==============================================================================
# 主执行流程
# ==============================================================================

# 执行依赖检查
install_dependencies

# 展示面板
draw_separator
echo -e "            ${CYAN}OpenWrt 24.10.4 设备系统状态监控看板 (SYSINFO)${NC}"
draw_separator

get_system_uptime
draw_separator

get_cpu_info
draw_separator

get_memory_info
draw_separator

get_disk_info
draw_separator

get_temperature_info
draw_separator

get_network_info
draw_separator

get_pppoe_uptime
draw_separator

get_docker_status
draw_separator

echo -e "                    ${WHITE}获取系统状态完成 - $(date "+%Y-%m-%d %H:%M:%S")${NC}"
draw_separator
