#!/bin/bash
# MySQL连接诊断脚本
# 用于诊断和修复MySQL外部连接问题

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 检查是否在正确的目录
check_directory() {
    if [[ ! -f "deploy.sh" ]]; then
        log_error "请在部署目录中运行此脚本 (应包含 deploy.sh)"
        exit 1
    fi
}

# 检查环境配置
check_environment_config() {
    log_info "检查环境配置..."
    
    if [[ -f "environments/.env.production" ]]; then
        source environments/.env.production
        
        log_info "数据库配置:"
        echo "  DB_HOST: $DB_HOST"
        echo "  DB_PORT: $DB_PORT"
        echo "  DB_NAME: $DB_NAME"
        echo "  DB_USER: $DB_USER"
        echo "  DB_PASSWORD: [HIDDEN]"
    else
        log_error "未找到生产环境配置文件"
        return 1
    fi
}

# 检查容器状态
check_container_status() {
    log_info "检查MySQL容器状态..."
    
    if docker ps --filter "name=anxin-mysql-prod" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep anxin-mysql-prod; then
        log_success "✓ MySQL容器正在运行"
        
        # 显示端口映射
        local ports=$(docker port anxin-mysql-prod 2>/dev/null || echo "无端口映射")
        log_info "端口映射: $ports"
    else
        log_error "✗ MySQL容器未运行"
        
        # 检查是否存在但已停止
        if docker ps -a --filter "name=anxin-mysql-prod" --format "{{.Names}}" | grep -q anxin-mysql-prod; then
            log_warn "MySQL容器存在但已停止"
            docker ps -a --filter "name=anxin-mysql-prod" --format "table {{.Names}}\t{{.Status}}"
        fi
        return 1
    fi
}

# 检查网络连接
check_network_connectivity() {
    log_info "检查网络连接..."
    
    if [[ -f "environments/.env.production" ]]; then
        source environments/.env.production
        
        # 检查端口是否开放
        log_info "检查端口 $DB_PORT 是否开放..."
        if netstat -tlnp 2>/dev/null | grep ":$DB_PORT " || ss -tlnp 2>/dev/null | grep ":$DB_PORT "; then
            log_success "✓ 端口 $DB_PORT 正在监听"
        else
            log_error "✗ 端口 $DB_PORT 未开放"
        fi
        
        # 测试本地连接
        log_info "测试本地连接..."
        if nc -z localhost "$DB_PORT" 2>/dev/null; then
            log_success "✓ 本地连接测试成功"
        else
            log_error "✗ 本地连接测试失败"
        fi
        
        # 测试容器内连接
        if docker ps --filter "name=anxin-mysql-prod" --format "{{.Names}}" | grep -q anxin-mysql-prod; then
            log_info "测试容器内连接..."
            if docker exec anxin-mysql-prod mysqladmin ping -h localhost -u root -p"$MYSQL_ROOT_PASSWORD" 2>/dev/null; then
                log_success "✓ 容器内连接测试成功"
            else
                log_error "✗ 容器内连接测试失败"
            fi
        fi
    fi
}

# 检查防火墙设置
check_firewall() {
    log_info "检查防火墙设置..."
    
    if [[ -f "environments/.env.production" ]]; then
        source environments/.env.production
        
        # 检查iptables规则
        if command -v iptables >/dev/null 2>&1; then
            log_info "检查iptables规则..."
            if iptables -L INPUT -n | grep -q "$DB_PORT"; then
                log_info "找到端口 $DB_PORT 的iptables规则"
                iptables -L INPUT -n | grep "$DB_PORT"
            else
                log_warn "未找到端口 $DB_PORT 的iptables规则"
            fi
        fi
        
        # 检查firewalld
        if command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active firewalld >/dev/null 2>&1; then
            log_info "检查firewalld规则..."
            if firewall-cmd --list-ports | grep -q "$DB_PORT"; then
                log_success "✓ 端口 $DB_PORT 已在firewalld中开放"
            else
                log_warn "端口 $DB_PORT 未在firewalld中开放"
            fi
        fi
        
        # 检查ufw
        if command -v ufw >/dev/null 2>&1; then
            log_info "检查ufw规则..."
            if ufw status | grep -q "$DB_PORT"; then
                log_success "✓ 端口 $DB_PORT 已在ufw中开放"
            else
                log_warn "端口 $DB_PORT 未在ufw中开放"
            fi
        fi
    fi
}

# 检查MySQL配置
check_mysql_config() {
    log_info "检查MySQL配置..."
    
    if docker ps --filter "name=anxin-mysql-prod" --format "{{.Names}}" | grep -q anxin-mysql-prod; then
        # 检查bind-address配置
        log_info "检查bind-address配置..."
        if docker exec anxin-mysql-prod mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SHOW VARIABLES LIKE 'bind_address';" 2>/dev/null; then
            log_success "✓ 获取bind_address配置成功"
        else
            log_error "✗ 无法获取bind_address配置"
        fi
        
        # 检查用户权限
        log_info "检查用户权限..."
        if [[ -f "environments/.env.production" ]]; then
            source environments/.env.production
            
            if docker exec anxin-mysql-prod mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SELECT User, Host FROM mysql.user WHERE User='$DB_USER';" 2>/dev/null; then
                log_success "✓ 获取用户权限信息成功"
            else
                log_error "✗ 无法获取用户权限信息"
            fi
        fi
    fi
}

# 测试外部连接
test_external_connection() {
    log_info "测试外部连接..."
    
    if [[ -f "environments/.env.production" ]]; then
        source environments/.env.production
        
        # 获取服务器外部IP
        local external_ip=$(curl -s ifconfig.me 2>/dev/null || curl -s ipinfo.io/ip 2>/dev/null || echo "unknown")
        log_info "服务器外部IP: $external_ip"
        
        # 测试从外部连接
        log_info "尝试从外部连接MySQL..."
        if timeout 10 mysql -h "$external_ip" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1;" 2>/dev/null; then
            log_success "✓ 外部连接测试成功"
        else
            log_error "✗ 外部连接测试失败"
            log_info "请检查:"
            echo "  1. 防火墙是否开放端口 $DB_PORT"
            echo "  2. MySQL用户是否允许远程连接"
            echo "  3. 网络安全组是否允许该端口"
        fi
    fi
}

# 修复常见问题
fix_common_issues() {
    log_info "修复常见问题..."
    
    if [[ -f "environments/.env.production" ]]; then
        source environments/.env.production
        
        # 1. 重启MySQL容器
        log_info "重启MySQL容器..."
        ./deploy.sh restart mysql -e production
        sleep 10
        
        # 2. 检查并修复用户权限
        if docker ps --filter "name=anxin-mysql-prod" --format "{{.Names}}" | grep -q anxin-mysql-prod; then
            log_info "修复用户权限..."
            
            # 创建用户并授权（如果不存在）
            docker exec anxin-mysql-prod mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "
                CREATE USER IF NOT EXISTS '$DB_USER'@'%' IDENTIFIED BY '$DB_PASSWORD';
                GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'%';
                FLUSH PRIVILEGES;
            " 2>/dev/null && log_success "✓ 用户权限修复完成" || log_error "✗ 用户权限修复失败"
        fi
        
        # 3. 开放防火墙端口（如果需要）
        if command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active firewalld >/dev/null 2>&1; then
            log_info "开放firewalld端口..."
            firewall-cmd --permanent --add-port="$DB_PORT/tcp" 2>/dev/null && \
            firewall-cmd --reload 2>/dev/null && \
            log_success "✓ firewalld端口开放完成" || log_warn "firewalld端口开放失败"
        fi
        
        if command -v ufw >/dev/null 2>&1; then
            log_info "开放ufw端口..."
            ufw allow "$DB_PORT/tcp" 2>/dev/null && \
            log_success "✓ ufw端口开放完成" || log_warn "ufw端口开放失败"
        fi
    fi
}

# 显示连接信息
show_connection_info() {
    log_info "MySQL连接信息:"
    echo "========================================"
    
    if [[ -f "environments/.env.production" ]]; then
        source environments/.env.production
        
        local external_ip=$(curl -s ifconfig.me 2>/dev/null || curl -s ipinfo.io/ip 2>/dev/null || echo "your-server-ip")
        
        echo "外部连接信息:"
        echo "  主机: $external_ip"
        echo "  端口: $DB_PORT"
        echo "  数据库: $DB_NAME"
        echo "  用户名: $DB_USER"
        echo "  密码: $DB_PASSWORD"
        echo ""
        echo "连接命令示例:"
        echo "  mysql -h $external_ip -P $DB_PORT -u $DB_USER -p$DB_PASSWORD $DB_NAME"
        echo ""
        echo "JDBC连接字符串:"
        echo "  jdbc:mysql://$external_ip:$DB_PORT/$DB_NAME?useUnicode=true&characterEncoding=utf8&useSSL=false"
    fi
    
    echo "========================================"
}

# 主函数
main() {
    local action=${1:-"diagnose"}
    
    log_info "MySQL连接诊断工具"
    echo "========================================"
    
    check_directory
    
    case $action in
        "diagnose")
            check_environment_config
            echo ""
            check_container_status
            echo ""
            check_network_connectivity
            echo ""
            check_firewall
            echo ""
            check_mysql_config
            echo ""
            test_external_connection
            echo ""
            show_connection_info
            ;;
        "fix")
            fix_common_issues
            echo ""
            main "diagnose"
            ;;
        "info")
            show_connection_info
            ;;
        *)
            echo "用法: $0 [diagnose|fix|info]"
            echo "  diagnose - 诊断连接问题（默认）"
            echo "  fix      - 修复常见问题"
            echo "  info     - 显示连接信息"
            exit 1
            ;;
    esac
    
    echo "========================================"
    log_success "操作完成!"
}

# 如果脚本被直接执行
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi