#!/bin/bash
################################################################################
# 39_middleware_conn.sh — 中间件连接检测
# 功能: 检测 Redis/MySQL/EMQX/FastDFS 连接状态和运行健康度
# 参考: middleware_check.sh, MiddlewareCheck.psm1
# 日期: 2026-07-22
# 修订: 2026-07-22 - 改用服务自带工具 ping 优先，宿主机端口辅助诊断
#        （避免容器内无 ss/netstat 导致误判"端口未监听"）
################################################################################

# 获取脚本所在目录并加载依赖
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

# 从配置获取容器匹配模式和端口
REDIS_CONTAINER="${CONTAINERS[redis]:-redis}"
MYSQL_CONTAINER="${CONTAINERS[mysql]:-mysql}"
EMQX_CONTAINER="${CONTAINERS[emqx]:-emqx}"
EMQX_MQTT_PORT="${EMQX_MQTT_PORT:-1883}"
EMQX_DASHBOARD_PORT="${EMQX_DASHBOARD_PORT:-18083}"
FASTDFS_CONTAINER="${CONTAINERS[ustorage]:-ustorage|storage}"

# ==================== Redis 连接检测 ====================

check_redis_connection() {
    local actual_container
    actual_container=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "$REDIS_CONTAINER" | head -1)

    if [ -z "$actual_container" ]; then
        output_result "MW_CONN_REDIS_STATUS" "未检测到容器"
        output_result "MW_CONN_REDIS_STATUS_LEVEL" "严重"
        return
    fi

    # redis-cli ping 测试（优先用密码，无密码也能测）
    local ping_result
    if [ -n "$REDIS_PASSWORD" ]; then
        ping_result=$(docker exec "$actual_container" redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>/dev/null)
    else
        ping_result=$(docker exec "$actual_container" redis-cli ping 2>/dev/null)
    fi

    if [ "$ping_result" = "PONG" ]; then
        # 获取版本和运行信息
        local version memory clients
        if [ -n "$REDIS_PASSWORD" ]; then
            version=$(docker exec "$actual_container" redis-cli -a "$REDIS_PASSWORD" --no-auth-warning \
                INFO server 2>/dev/null | grep "redis_version" | cut -d: -f2 | tr -d '\r')
            memory=$(docker exec "$actual_container" redis-cli -a "$REDIS_PASSWORD" --no-auth-warning \
                INFO memory 2>/dev/null | grep "used_memory_human:" | cut -d: -f2 | tr -d '\r')
            clients=$(docker exec "$actual_container" redis-cli -a "$REDIS_PASSWORD" --no-auth-warning \
                INFO clients 2>/dev/null | grep "connected_clients:" | cut -d: -f2 | tr -d '\r')
        else
            version=$(docker exec "$actual_container" redis-cli INFO server 2>/dev/null | grep "redis_version" | cut -d: -f2 | tr -d '\r')
            memory=$(docker exec "$actual_container" redis-cli INFO memory 2>/dev/null | grep "used_memory_human:" | cut -d: -f2 | tr -d '\r')
            clients=$(docker exec "$actual_container" redis-cli INFO clients 2>/dev/null | grep "connected_clients:" | cut -d: -f2 | tr -d '\r')
        fi

        output_result "MW_CONN_REDIS_STATUS" "运行中"
        output_result "MW_CONN_REDIS_STATUS_LEVEL" "正常"
        output_result "MW_CONN_REDIS_VERSION" "${version:-未知}"
        output_result "MW_CONN_REDIS_MEMORY" "${memory:-未知}"
        output_result "MW_CONN_REDIS_CLIENTS" "${clients:-0}"
    elif [ "$ping_result" = "NOAUTH" ] || echo "$ping_result" | grep -qi "auth"; then
        # 需要密码但未配置或密码错误
        output_result "MW_CONN_REDIS_STATUS" "需密码认证"
        output_result "MW_CONN_REDIS_STATUS_LEVEL" "警告"
        output_result "MW_CONN_REDIS_VERSION" "未知"
        output_result "MW_CONN_REDIS_MEMORY" "未知"
        output_result "MW_CONN_REDIS_CLIENTS" "未知"
    else
        # ping 失败，辅助诊断：从宿主机检查端口
        local host_port
        host_port=$(ss -tlnp 2>/dev/null | grep -oP ':\K6379' | head -1)
        if [ -n "$host_port" ]; then
            output_result "MW_CONN_REDIS_STATUS" "端口监听但连接失败"
            output_result "MW_CONN_REDIS_STATUS_LEVEL" "严重"
        else
            output_result "MW_CONN_REDIS_STATUS" "连接失败"
            output_result "MW_CONN_REDIS_STATUS_LEVEL" "严重"
        fi
    fi
}

# ==================== MySQL 连接检测 ====================

check_mysql_connection() {
    local actual_container
    actual_container=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "$MYSQL_CONTAINER" | head -1)

    if [ -z "$actual_container" ]; then
        output_result "MW_CONN_MYSQL_STATUS" "未检测到容器"
        output_result "MW_CONN_MYSQL_STATUS_LEVEL" "严重"
        return
    fi

    # mysqladmin ping 测试（在容器内执行，连内部 3306）
    local ping_result
    ping_result=$(docker exec "$actual_container" mysqladmin -uroot -p"$MYSQL_PASSWORD" ping 2>/dev/null | grep -c "alive")

    if [ "$ping_result" -gt 0 ]; then
        # 获取版本信息
        local version
        version=$(docker exec "$actual_container" mysql -uroot -p"$MYSQL_PASSWORD" -N -e \
            "SELECT VERSION();" 2>/dev/null)

        output_result "MW_CONN_MYSQL_STATUS" "运行中"
        output_result "MW_CONN_MYSQL_STATUS_LEVEL" "正常"
        output_result "MW_CONN_MYSQL_VERSION" "${version:-未知}"
    else
        # ping 失败，辅助诊断：检查容器内是否有 mysql 进程
        local mysql_proc
        mysql_proc=$(docker exec "$actual_container" ps aux 2>/dev/null | grep -v grep | grep -cE 'mysqld' || echo "0")
        if [ "$mysql_proc" -gt 0 ]; then
            output_result "MW_CONN_MYSQL_STATUS" "进程存在但连接失败"
            output_result "MW_CONN_MYSQL_STATUS_LEVEL" "严重"
        else
            output_result "MW_CONN_MYSQL_STATUS" "连接失败"
            output_result "MW_CONN_MYSQL_STATUS_LEVEL" "严重"
        fi
    fi
}

# ==================== EMQX 连接检测 ====================

check_emqx_connection() {
    local actual_container
    actual_container=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "$EMQX_CONTAINER" | head -1)

    if [ -z "$actual_container" ]; then
        output_result "MW_CONN_EMQX_STATUS" "未检测到容器"
        output_result "MW_CONN_EMQX_STATUS_LEVEL" "严重"
        return
    fi

    # 从宿主机检查 MQTT 端口监听（EMQX 通常有端口映射）
    local mqtt_listening
    mqtt_listening=$(ss -tlnp 2>/dev/null | grep -q ":${EMQX_MQTT_PORT}" && echo 'yes' || echo 'no')

    # 从宿主机检查 Dashboard 端口
    local dashboard_listening
    dashboard_listening=$(ss -tlnp 2>/dev/null | grep -q ":${EMQX_DASHBOARD_PORT}" && echo 'yes' || echo 'no')

    # 调用 Dashboard API 验证服务状态
    local api_status=""
    if [ "$dashboard_listening" = "yes" ]; then
        local http_code
        http_code=$(curl -s -o /dev/null -w '%{http_code}' \
            "http://localhost:${EMQX_DASHBOARD_PORT}/api/v5/status" 2>/dev/null)
        api_status="HTTP $http_code"
    else
        api_status="Dashboard 未监听"
    fi

    # 检查进程状态
    local proc_count
    proc_count=$(docker exec "$actual_container" ps aux 2>/dev/null | \
        grep -v grep | grep -cE 'emqx|beam' || echo "0")

    if [ "$mqtt_listening" = "yes" ] && [ "$proc_count" -ge 1 ]; then
        output_result "MW_CONN_EMQX_STATUS" "运行中"
        output_result "MW_CONN_EMQX_STATUS_LEVEL" "正常"
    elif [ "$proc_count" -ge 1 ]; then
        output_result "MW_CONN_EMQX_STATUS" "MQTT 端口未监听"
        output_result "MW_CONN_EMQX_STATUS_LEVEL" "严重"
    else
        output_result "MW_CONN_EMQX_STATUS" "进程异常"
        output_result "MW_CONN_EMQX_STATUS_LEVEL" "严重"
    fi

    output_result "MW_CONN_EMQX_MQTT_PORT" "$EMQX_MQTT_PORT"
    output_result "MW_CONN_EMQX_DASHBOARD" "$EMQX_DASHBOARD_PORT"
    output_result "MW_CONN_EMQX_API_STATUS" "$api_status"
}

# ==================== FastDFS 连接检测 ====================

check_fastdfs_connection() {
    local actual_container
    actual_container=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "$FASTDFS_CONTAINER" | head -1)

    if [ -z "$actual_container" ]; then
        output_result "MW_CONN_FASTDFS_STATUS" "未检测到容器"
        output_result "MW_CONN_FASTDFS_STATUS_LEVEL" "严重"
        return
    fi

    # 获取网络模式
    local network_mode
    network_mode=$(docker inspect "$actual_container" 2>/dev/null | \
        grep -oP '"NetworkMode": "\K[^"]+' | head -1)

    output_result "MW_CONN_FASTDFS_NETWORK" "${network_mode:-未知}"

    # 根据网络模式检查进程
    local tracker_count=0
    local storage_count=0

    if [ "$network_mode" = "host" ]; then
        tracker_count=$(ps aux 2>/dev/null | grep -v grep | grep 'fdfs_trackerd' | wc -l)
        storage_count=$(ps aux 2>/dev/null | grep -v grep | grep 'fdfs_storaged' | wc -l)
    else
        tracker_count=$(docker exec "$actual_container" ps aux 2>/dev/null | \
            grep -v grep | grep 'fdfs_trackerd' | wc -l)
        storage_count=$(docker exec "$actual_container" ps aux 2>/dev/null | \
            grep -v grep | grep 'fdfs_storaged' | wc -l)
    fi

    if [ "$tracker_count" -gt 0 ] && [ "$storage_count" -gt 0 ]; then
        output_result "MW_CONN_FASTDFS_STATUS" "运行中"
        output_result "MW_CONN_FASTDFS_STATUS_LEVEL" "正常"
    else
        output_result "MW_CONN_FASTDFS_STATUS" "进程异常"
        output_result "MW_CONN_FASTDFS_STATUS_LEVEL" "严重"
    fi
}

# ==================== 主检测流程 ====================

main() {
    log_info "开始中间件连接检测..."

    set +e

    check_redis_connection 2>/dev/null || true
    check_mysql_connection 2>/dev/null || true
    check_emqx_connection 2>/dev/null || true
    check_fastdfs_connection 2>/dev/null || true

    log_info "中间件连接检测完成"
}

main
