#!/bin/bash
################################################################################
# Docker基础检测模块
# 功能: 检测Docker容器状态、资源使用、健康检查、日志大小等
# 作者: Claude Code
# 日期: 2026-05-09
################################################################################

# 获取脚本所在目录并加载依赖
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="${LIB_DIR:-/tmp/check_modules}"

# 加载配置文件和通用函数库
if [ -f "$LIB_DIR/lib/config.sh" ]; then
    source "$LIB_DIR/lib/config.sh"
else
    echo "ERROR: 配置文件不存在: $LIB_DIR/lib/config.sh"
    exit 1
fi

if [ -f "$LIB_DIR/lib/common.sh" ]; then
    source "$LIB_DIR/lib/common.sh"
else
    echo "ERROR: 通用函数库不存在: $LIB_DIR/lib/common.sh"
    exit 1
fi

# ==================== 检测函数 ====================

# 检测 Docker 命令是否需要 sudo
_detect_docker_sudo() {
    # 测试 docker ps 是否需要权限
    if docker ps &> /dev/null; then
        DOCKER_CMD="docker"
    elif sudo -n docker ps &> /dev/null 2>&1; then
        DOCKER_CMD="sudo docker"
    else
        DOCKER_CMD="docker"  # 降级，后续会报错
    fi
}

# 检测Docker服务状态
check_docker_service() {
    local docker_status="未知"

    # 首次调用时检测是否需要 sudo
    if [ -z "$DOCKER_CMD" ]; then
        _detect_docker_sudo
    fi

    if command -v docker &> /dev/null; then
        if $DOCKER_CMD ps &> /dev/null; then
            docker_status="运行中"
        else
            docker_status="无权限"
        fi
    else
        docker_status="未安装"
    fi

    output_result "DOCKER_SERVICE_STATUS" "$docker_status"

    if [ "$docker_status" = "运行中" ]; then
        output_result "DOCKER_SERVICE_LEVEL" "正常"
    else
        output_result "DOCKER_SERVICE_LEVEL" "严重"
        echo "ERROR:Docker服务异常: ${docker_status}"
    fi
}

# 检测容器状态列表
check_container_status() {
    local running_count=0
    local stopped_count=0
    local total_count=0

    if ! command -v docker &> /dev/null; then
        return
    fi

    # 获取所有容器
    local containers
    containers=$($DOCKER_CMD ps -a --format "{{.Names}}\t{{.Status}}" 2>/dev/null)

    if [ -n "$containers" ]; then
        total_count=$(echo "$containers" | wc -l)
        running_count=$(echo "$containers" | grep -c "Up" || echo "0")
        stopped_count=$((total_count - running_count))

        output_result "CONTAINER_TOTAL" "$total_count"
        output_result "CONTAINER_RUNNING" "$running_count"
        output_result "CONTAINER_STOPPED" "$stopped_count"

        # 检查每个配置的容器
        for key in "${!CONTAINERS[@]}"; do
            local container_name="${CONTAINERS[$key]}"
            check_single_container "$container_name" "$key"
        done
    fi
}

# 检测单个容器状态
check_single_container() {
    local container_name=$1
    local container_key=$2

    if [ -z "$DOCKER_CMD" ]; then
        _detect_docker_sudo
    fi

    if ! $DOCKER_CMD ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
        output_result "CONTAINER_${container_key}_EXISTS" "否"
        output_result "CONTAINER_${container_key}_STATUS" "不存在"
        return
    fi

    output_result "CONTAINER_${container_key}_EXISTS" "是"

    # 检查容器状态
    local container_status
    container_status=$($DOCKER_CMD inspect --format="{{.State.Status}}" "$container_name" 2>/dev/null)

    if [ "$container_status" = "running" ]; then
        output_result "CONTAINER_${container_key}_STATUS" "运行中"
        output_result "CONTAINER_${container_key}_LEVEL" "正常"
    else
        output_result "CONTAINER_${container_key}_STATUS" "$container_status"
        output_result "CONTAINER_${container_key}_LEVEL" "警告"
    fi

    # 检查重启次数
    local restart_count
    restart_count=$($DOCKER_CMD inspect --format="{{.RestartCount}}" "$container_name" 2>/dev/null)

    if [ -n "$restart_count" ] && [ "$restart_count" -gt 0 ]; then
        output_result "CONTAINER_${container_key}_RESTART" "$restart_count"

        if [ "$restart_count" -gt 5 ]; then
            output_result "CONTAINER_${container_key}_RESTART_LEVEL" "严重"
        else
            output_result "CONTAINER_${container_key}_RESTART_LEVEL" "警告"
        fi
    else
        output_result "CONTAINER_${container_key}_RESTART" "0"
    fi

    # 获取容器IP
    local container_ip
    container_ip=$($DOCKER_CMD inspect --format="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" "$container_name" 2>/dev/null)

    if [ -n "$container_ip" ]; then
        output_result "CONTAINER_${container_key}_IP" "$container_ip"
    fi

    # 获取端口映射
    local ports
    ports=$($DOCKER_CMD port "$container_name" 2>/dev/null)

    if [ -n "$ports" ]; then
        output_result "CONTAINER_${container_key}_PORTS" "$ports"
    fi
}

# 检测容器资源使用
check_container_resources() {
    if [ -z "$DOCKER_CMD" ]; then
        _detect_docker_sudo
    fi

    if ! command -v docker &> /dev/null; then
        return
    fi

    # 获取运行中的容器资源使用情况
    local stats
    stats=$($DOCKER_CMD stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" 2>/dev/null)

    if [ -n "$stats" ]; then
        # 跳过标题行，处理每个容器
        echo "$stats" | tail -n +2 | while IFS=$'\t' read -r name cpu mem_usage mem_perc; do
            if [ -n "$name" ]; then
                # 清理容器名中的 /
                local clean_name=$(echo "$name" | sed 's/\///g')
                local key_name=$(echo "$clean_name" | tr '[:lower:]' '[:upper:]')

                output_result "DOCKER_${key_name}_CPU" "$cpu"
                output_result "DOCKER_${key_name}_MEM" "$mem_usage"
                output_result "DOCKER_${key_name}_MEM_PERC" "$mem_perc"

                # 检查内存使用率
                if [ -n "$mem_perc" ]; then
                    local mem_value=$(echo "$mem_perc" | sed 's/%//')
                    if [ -n "$mem_value" ] && [ "$mem_value" -gt 90 ]; then
                        output_result "DOCKER_${key_name}_MEM_LEVEL" "严重"
                    elif [ -n "$mem_value" ] && [ "$mem_value" -gt 80 ]; then
                        output_result "DOCKER_${key_name}_MEM_LEVEL" "警告"
                    else
                        output_result "DOCKER_${key_name}_MEM_LEVEL" "正常"
                    fi
                fi
            fi
        done
    fi
}

# 检测容器健康状态
check_container_health() {
    if [ -z "$DOCKER_CMD" ]; then
        _detect_docker_sudo
    fi

    if ! command -v docker &> /dev/null; then
        return
    fi

    # 检查关键容器的健康状态
    for key in "mysql" "redis" "emqx"; do
        local container_name="${CONTAINERS[$key]}"

        if [ -z "$container_name" ]; then
            continue
        fi

        # 检查容器是否存在
        if ! $DOCKER_CMD ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
            continue
        fi

        # 检查健康状态
        local health_status
        health_status=$($DOCKER_CMD inspect --format="{{if .State.Health}}{{.State.Health.Status}}{{else}}no healthcheck{{end}}" "$container_name" 2>/dev/null)

        if [ -n "$health_status" ] && [ "$health_status" != "no healthcheck" ]; then
            output_result "HEALTH_${container_name}" "$health_status"

            if [ "$health_status" = "healthy" ]; then
                output_result "HEALTH_${container_name}_LEVEL" "正常"
            elif [ "$health_status" = "unhealthy" ]; then
                output_result "HEALTH_${container_name}_LEVEL" "严重"
                echo "ERROR:容器${container_name}健康检查失败"
            else
                output_result "HEALTH_${container_name}_LEVEL" "警告"
            fi
        fi
    done
}

# 检测容器日志大小
check_container_logs() {
    if [ -z "$DOCKER_CMD" ]; then
        _detect_docker_sudo
    fi

    if ! command -v docker &> /dev/null; then
        return
    fi

    local large_logs=0

    # 获取运行中容器的日志路径
    $DOCKER_CMD ps --format "{{.Names}}" | while read -r container_name; do
        if [ -n "$container_name" ]; then
            local log_path
            log_path=$($DOCKER_CMD inspect --format="{{.LogPath}}" "$container_name" 2>/dev/null)

            if [ -f "$log_path" ]; then
                local size_bytes
                size_bytes=$(stat -c%s "$log_path" 2>/dev/null || stat -f%z "$log_path" 2>/dev/null)

                if [ -n "$size_bytes" ]; then
                    local size_mb=$((size_bytes / 1024 / 1024))

                    local clean_name=$(echo "$container_name" | sed 's/\///g')
                    local key_name=$(echo "$clean_name" | tr '[:lower:]' '[:upper:]')

                    output_result "LOG_${key_name}_SIZE" "${size_mb}MB"

                    if [ "$size_mb" -gt 100 ]; then
                        output_result "LOG_${key_name}_LEVEL" "严重"
                        large_logs=$((large_logs + 1))
                    elif [ "$size_mb" -gt 50 ]; then
                        output_result "LOG_${key_name}_LEVEL" "警告"
                    else
                        output_result "LOG_${key_name}_LEVEL" "正常"
                    fi
                fi
            fi
        fi
    done

    output_result "DOCKER_LARGE_LOGS" "$large_logs"
}

# 检测Docker磁盘使用
check_docker_disk() {
    if [ -z "$DOCKER_CMD" ]; then
        _detect_docker_sudo
    fi

    if ! command -v docker &> /dev/null; then
        return
    fi

    local disk_usage
    disk_usage=$($DOCKER_CMD system df 2>/dev/null)

    if [ -n "$disk_usage" ]; then
        # 解析磁盘使用情况
        local images_size=$(echo "$disk_usage" | grep "^Images" | awk '{print $3}' | head -1)
        local containers_size=$(echo "$disk_usage" | grep "^Containers" | awk '{print $3}' | head -1)
        local volumes_size=$(echo "$disk_usage" | grep "^Local Volumes" | awk '{print $3}' | head -1)

        if [ -n "$images_size" ]; then
            output_result "DOCKER_IMAGES_SIZE" "$images_size"
        fi

        if [ -n "$containers_size" ]; then
            output_result "DOCKER_CONTAINERS_SIZE" "$containers_size"
        fi

        if [ -n "$volumes_size" ]; then
            output_result "DOCKER_VOLUMES_SIZE" "$volumes_size"
        fi
    fi
}

# 检测Docker网络
check_docker_network() {
    if [ -z "$DOCKER_CMD" ]; then
        _detect_docker_sudo
    fi

    if ! command -v docker &> /dev/null; then
        return
    fi

    local network_count
    network_count=$($DOCKER_CMD network ls 2>/dev/null | grep -c "^" || echo "0")
    network_count=$((network_count - 1))  # 减去标题行

    output_result "DOCKER_NETWORKS" "$network_count"
}

# ==================== 主检测流程 ====================
main() {
    log_info "开始Docker基础检测..."

    # 执行各项检测
    check_docker_service
    check_container_status
    check_container_resources
    check_container_health
    check_container_logs
    check_docker_disk
    check_docker_network

    log_info "Docker基础检测完成"
}

# 执行主函数
main
