#!/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系统信息
check_docker_system_info() {
    local docker_version server_version storage_driver

    docker_version=$(docker version --format '{{.Server.Version}}' 2>/dev/null)
    server_version=$(docker version --format '{{.Server.APIVersion}}' 2>/dev/null)
    storage_driver=$(docker info --format '{{.Driver}}' 2>/dev/null)

    if [ -n "$docker_version" ]; then
        output_result "DOCKER_VERSION" "$docker_version"
    else
        output_result "DOCKER_VERSION" "获取失败"
    fi

    if [ -n "$server_version" ]; then
        output_result "DOCKER_API_VERSION" "$server_version"
    fi

    if [ -n "$storage_driver" ]; then
        output_result "DOCKER_STORAGE_DRIVER" "$storage_driver"
    fi
}

# 检测Docker镜像列表
check_docker_images() {
    local image_count dangling_count

    image_count=$(docker images -q 2>/dev/null | wc -l)
    dangling_count=$(docker images -f "dangling=true" -q 2>/dev/null | wc -l)

    output_result "DOCKER_IMAGES_COUNT" "$image_count"
    output_result "DOCKER_IMAGES_DANGLING" "$dangling_count"

    # 获取TOP5最大镜像
    local top_images
    top_images=$(docker images --format "{{.Repository}}:{{.Tag}}\t{{.Size}}" 2>/dev/null | sort -k2 -h | tail -5 | tr '\n' '|' | sed 's/|$//')

    if [ -n "$top_images" ]; then
        output_result "DOCKER_IMAGES_TOP5" "$top_images"
    else
        output_result "DOCKER_IMAGES_TOP5" "无"
    fi
}

# 检测Docker网络详情
check_docker_network_detail() {
    local network_count bridge_count overlay_count

    network_count=$(docker network ls 2>/dev/null | grep -c "^" || echo "0")
    network_count=$((network_count - 1))

    bridge_count=$(docker network ls 2>/dev/null | grep -c "bridge" || echo "0")
    overlay_count=$(docker network ls 2>/dev/null | grep -c "overlay" || echo "0")

    output_result "DOCKER_NETWORK_COUNT" "$network_count"
    output_result "DOCKER_NETWORK_BRIDGE" "$bridge_count"
    output_result "DOCKER_NETWORK_OVERLAY" "$overlay_count"

    # 获取网络列表
    local network_list
    network_list=$(docker network ls --format "{{.Name}}\t{{.Driver}}\t{{.Scope}}" 2>/dev/null | tr '\n' '|' | sed 's/|$//')

    if [ -n "$network_list" ]; then
        output_result "DOCKER_NETWORK_LIST" "$network_list"
    fi
}

# 检测Docker卷
check_docker_volumes() {
    local volume_count unused_count

    volume_count=$(docker volume ls -q 2>/dev/null | wc -l)

    output_result "DOCKER_VOLUMES_COUNT" "$volume_count"

    # 获取卷列表
    local volume_list
    volume_list=$(docker volume ls --format "{{.Name}}\t{{.Driver}}" 2>/dev/null | tr '\n' '|' | sed 's/|$//')

    if [ -n "$volume_list" ]; then
        output_result "DOCKER_VOLUMES_LIST" "$volume_list"
    fi
}

# 检测容器资源限制
check_container_limits() {
    for key in "${!CONTAINERS[@]}"; do
        local container_name="${CONTAINERS[$key]}"

        if ! docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
            continue
        fi

        # 获取CPU限制
        local cpu_quota cpu_period
        cpu_quota=$(docker inspect --format='{{.HostConfig.CpuQuota}}' "$container_name" 2>/dev/null)
        cpu_period=$(docker inspect --format='{{.HostConfig.CpuPeriod}}' "$container_name" 2>/dev/null)

        if [ -n "$cpu_quota" ] && [ "$cpu_quota" != "0" ]; then
            local cpu_limit=$((cpu_quota * 100 / cpu_period))
            output_result "LIMIT_${container_name}_CPU" "${cpu_limit}%"
        else
            output_result "LIMIT_${container_name}_CPU" "无限制"
        fi

        # 获取内存限制
        local memory_limit
        memory_limit=$(docker inspect --format='{{.HostConfig.Memory}}' "$container_name" 2>/dev/null)

        if [ -n "$memory_limit" ] && [ "$memory_limit" != "0" ]; then
            local memory_mb=$((memory_limit / 1024 / 1024))
            output_result "LIMIT_${container_name}_MEMORY" "${memory_mb}MB"
        else
            output_result "LIMIT_${container_name}_MEMORY" "无限制"
        fi
    done
}

# 检测容器进程详情（遍历所有已配置容器）
check_container_processes() {
    for key in "${!CONTAINERS[@]}"; do
        local container_name
        container_name=$(resolve_container "$key" 2>/dev/null)

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

        # 获取容器内进程数
        local process_count
        process_count=$(docker exec "$container_name" ps aux 2>/dev/null | wc -l)
        process_count=$((process_count - 1))

        if [ -n "$process_count" ] && [ "$process_count" -gt 0 ]; then
            output_result "PROCESSES_${key}" "$process_count"
            output_result "PROCESSES_${container_name}" "$process_count"
        fi
    done
}

# 检测容器文件系统使用
check_container_fs_usage() {
    for key in "${!CONTAINERS[@]}"; do
        local container_name="${CONTAINERS[$key]}"

        if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
            continue
        fi

        # 获取容器根文件系统大小
        local size_rw size_rootfs
        size_rw=$(docker inspect --format='{{.SizeRw}}' "$container_name" 2>/dev/null)
        size_rootfs=$(docker inspect --format='{{.SizeRootFs}}' "$container_name" 2>/dev/null)

        if [ -n "$size_rw" ] && [ "$size_rw" != "0" ]; then
            local rw_mb=$((size_rw / 1024 / 1024))
            output_result "FS_${container_name}_RW" "${rw_mb}MB"
        fi

        if [ -n "$size_rootfs" ] && [ "$size_rootfs" != "0" ]; then
            local rootfs_mb=$((size_rootfs / 1024 / 1024))
            output_result "FS_${container_name}_ROOT" "${rootfs_mb}MB"
        fi
    done
}

# 检测Docker事件（最近的错误和警告）
check_docker_events() {
    # 获取最近1小时的事件
    local error_events warn_events

    error_events=$(docker events --since 1h --until 1m --format '{{$line}}' 2>/dev/null | grep -i "error" | wc -l)
    warn_events=$(docker events --since 1h --until 1m --format '{{$line}}' 2>/dev/null | grep -E "warn|kill|die" | wc -l)

    output_result "DOCKER_EVENTS_ERROR" "$error_events"
    output_result "DOCKER_EVENTS_WARN" "$warn_events"

    if [ "$error_events" -gt 0 ]; then
        output_result "DOCKER_EVENTS_LEVEL" "严重"
    elif [ "$warn_events" -gt 0 ]; then
        output_result "DOCKER_EVENTS_LEVEL" "警告"
    else
        output_result "DOCKER_EVENTS_LEVEL" "正常"
    fi
}

# 检测容器重启历史
check_container_restart_history() {
    for key in "${!CONTAINERS[@]}"; do
        local container_name="${CONTAINERS[$key]}"

        if ! docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
            continue
        fi

        # 获取重启次数
        local restart_count
        restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)

        if [ -n "$restart_count" ]; then
            output_result "RESTART_COUNT_${container_name}" "$restart_count"
        fi

        # 获取上次重启时间
        local restarted_at
        restarted_at=$(docker inspect --format='{{.State.StartedAt}}' "$container_name" 2>/dev/null)

        if [ -n "$restarted_at" ]; then
            output_result "RESTART_TIME_${container_name}" "$restarted_at"
        fi
    done
}

# 检测Docker守护进程资源
check_docker_daemon_resources() {
    # 获取Docker守护进程的CPU和内存使用
    local docker_pid
    docker_pid=$(pgrep dockerd | head -1)

    if [ -n "$docker_pid" ]; then
        local docker_cpu docker_mem
        docker_cpu=$(ps -p "$docker_pid" -o %cpu --no-headers 2>/dev/null | tr -d ' ')
        docker_mem=$(ps -p "$docker_pid" -o %mem --no-headers 2>/dev/null | tr -d ' ')

        if [ -n "$docker_cpu" ]; then
            output_result "DOCKER_DAEMON_CPU" "${docker_cpu}%"
        fi

        if [ -n "$docker_mem" ]; then
            output_result "DOCKER_DAEMON_MEM" "${docker_mem}%"
        fi
    fi
}

# 检测容器挂载点
check_container_mounts() {
    for key in "${!CONTAINERS[@]}"; do
        local container_name="${CONTAINERS[$key]}"

        if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
            continue
        fi

        # 获取挂载点数量
        local mount_count
        mount_count=$(docker inspect --format='{{len .Mounts}}' "$container_name" 2>/dev/null)

        if [ -n "$mount_count" ] && [ "$mount_count" -gt 0 ]; then
            output_result "MOUNTS_${container_name}_COUNT" "$mount_count"

            # 获取挂载点列表
            local mounts
            mounts=$(docker inspect --format='{{range .Mounts}}{{.Source}}:{{.Destination}}|{{end}}' "$container_name" 2>/dev/null | sed 's/|$//')

            if [ -n "$mounts" ]; then
                output_result "MOUNTS_${container_name}_LIST" "$mounts"
            fi
        fi
    done
}

# 检测容器环境变量（安全检查）
check_container_env() {
    # 检查是否有明文密码等敏感信息
    for key in "mysql" "redis"; do
        local container_name="${CONTAINERS[$key]}"

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

        if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
            continue
        fi

        # 获取环境变量数量
        local env_count
        env_count=$(docker inspect --format='{{len .Config.Env}}' "$container_name" 2>/dev/null)

        if [ -n "$env_count" ]; then
            output_result "ENV_${container_name}_COUNT" "$env_count"
        fi
    done
}

# 检测Docker构建缓存
check_docker_build_cache() {
    # 获取构建缓存大小（通过docker system df）
    local build_cache
    build_cache=$(docker system df --format "{{.BuildCache}}" 2>/dev/null | grep -v "Build Cache" | head -1)

    if [ -n "$build_cache" ]; then
        output_result "DOCKER_BUILD_CACHE" "$build_cache"
    fi
}

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

    # 检查Docker是否可用
    if ! command -v docker &> /dev/null; then
        log_error "Docker未安装"
        return 1
    fi

    # 执行各项深度检测
    check_docker_system_info
    check_docker_images
    check_docker_network_detail
    check_docker_volumes
    check_container_limits
    check_container_processes
    check_container_fs_usage
    check_docker_events
    check_container_restart_history
    check_docker_daemon_resources
    check_container_mounts
    check_container_env
    check_docker_build_cache

    log_info "Docker深度检测完成"
}

# 执行主函数
main
