<?php
/**
 * SMTP诊断工具
 * 帮助诊断SMTP配置问题
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

/**
 * 获取PHP和服务器环境信息
 */
function nenghui_get_smtp_diagnostic_info() {
    $info = [];
    
    // PHP版本
    $info['php_version'] = PHP_VERSION;
    
    // 检查必要的PHP扩展
    $info['extensions'] = [
        'openssl' => extension_loaded('openssl'),
        'sockets' => extension_loaded('sockets'),
        'curl' => extension_loaded('curl'),
        'mbstring' => extension_loaded('mbstring')
    ];
    
    // 检查OpenSSL支持的协议
    if (extension_loaded('openssl')) {
        $info['openssl_version'] = OPENSSL_VERSION_TEXT;
        $info['stream_crypto_methods'] = stream_get_transports();
    }
    
    // 检查allow_url_fopen
    $info['allow_url_fopen'] = ini_get('allow_url_fopen') ? 'Yes' : 'No';
    
    // 检查用户代理
    $info['user_agent'] = ini_get('user_agent');
    
    // 检查默认socket超时
    $info['default_socket_timeout'] = ini_get('default_socket_timeout');
    
    return $info;
}

/**
 * 测试端口连接
 */
function nenghui_test_port_connection($host, $port, $timeout = 10) {
    $result = [
        'success' => false,
        'message' => '',
        'time' => 0,
        'methods_tried' => []
    ];
    
    // 方法1: 使用fsockopen
    $start_time = microtime(true);
    $socket = @fsockopen($host, $port, $errno, $errstr, $timeout);
    $end_time = microtime(true);
    $result['time'] = round(($end_time - $start_time) * 1000, 2);
    
    if ($socket) {
        $result['success'] = true;
        $result['message'] = "✅ 成功连接到 {$host}:{$port} (fsockopen, 耗时: {$result['time']}ms)";
        $result['methods_tried'][] = 'fsockopen: 成功';
        fclose($socket);
        return $result;
    } else {
        $result['methods_tried'][] = "fsockopen: 失败 - {$errstr} ({$errno})";
    }
    
    // 方法2: 使用stream_socket_client
    $start_time = microtime(true);
    $context = stream_context_create([
        'socket' => [
            'bindto' => '0:0',
        ]
    ]);
    $socket = @stream_socket_client(
        "tcp://{$host}:{$port}",
        $errno2,
        $errstr2,
        $timeout,
        STREAM_CLIENT_CONNECT,
        $context
    );
    $end_time = microtime(true);
    $time2 = round(($end_time - $start_time) * 1000, 2);
    
    if ($socket) {
        $result['success'] = true;
        $result['message'] = "✅ 成功连接到 {$host}:{$port} (stream_socket_client, 耗时: {$time2}ms)";
        $result['methods_tried'][] = 'stream_socket_client: 成功';
        $result['time'] = $time2;
        fclose($socket);
        return $result;
    } else {
        $result['methods_tried'][] = "stream_socket_client: 失败 - {$errstr2} ({$errno2})";
    }
    
    // 方法3: 使用curl (如果可用)
    if (function_exists('curl_init')) {
        $start_time = microtime(true);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "http://{$host}:{$port}");
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_NOBODY, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
        
        $response = curl_exec($ch);
        $curl_error = curl_error($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $connect_time = curl_getinfo($ch, CURLINFO_CONNECT_TIME) * 1000;
        curl_close($ch);
        
        $end_time = microtime(true);
        $time3 = round(($end_time - $start_time) * 1000, 2);
        
        if ($response !== false || $http_code > 0) {
            $result['success'] = true;
            $result['message'] = "✅ 成功连接到 {$host}:{$port} (curl, 耗时: {$time3}ms, HTTP状态: {$http_code})";
            $result['methods_tried'][] = 'curl: 成功';
            $result['time'] = $time3;
            return $result;
        } else {
            $result['methods_tried'][] = "curl: 失败 - {$curl_error}";
        }
    }
    
    // 所有方法都失败
    $result['message'] = "❌ 无法连接到 {$host}:{$port}\n";
    $result['message'] .= "尝试的连接方法:\n";
    foreach ($result['methods_tried'] as $method) {
        $result['message'] .= "• {$method}\n";
    }
    
    // 添加诊断建议
    $result['message'] .= "\n🔍 可能的原因:\n";
    
    // 针对端口25的特殊提示
    if ($port == 25) {
        $result['message'] .= "• ⚠️ 端口25被封禁：大多数云服务商（阿里云、腾讯云等）默认封禁端口25\n";
        $result['message'] .= "• 🔧 解决方案：改用端口587（TLS）或465（SSL）\n";
        $result['message'] .= "• 📧 建议配置：使用STARTTLS加密方式，端口587\n";
    } else {
        $result['message'] .= "• 服务器防火墙阻止了端口 {$port}\n";
    }
    
    $result['message'] .= "• SMTP服务未启动或未监听此端口\n";
    $result['message'] .= "• 网络连接问题或DNS解析失败\n";
    $result['message'] .= "• 服务器IP地址或域名不正确\n";
    
    // 添加云服务商特殊说明
    if ($port == 25) {
        $result['message'] .= "\n💡 云服务商端口限制说明:\n";
        $result['message'] .= "• 阿里云ECS：默认封禁25端口，无法申请解封\n";
        $result['message'] .= "• 腾讯云CVM：默认封禁25端口，企业用户可申请解封\n";
        $result['message'] .= "• 建议使用端口587或465，配合TLS/SSL加密\n";
    }
    
    return $result;
}

/**
 * 测试SSL/TLS连接
 */
function nenghui_test_ssl_connection($host, $port, $crypto_method = 'tls') {
    $result = [
        'success' => false,
        'message' => '',
        'certificate_info' => null
    ];
    
    $context = stream_context_create([
        'ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true
        ]
    ]);
    
    $protocol = ($crypto_method === 'ssl') ? 'ssl' : 'tls';
    $connection_string = "{$protocol}://{$host}:{$port}";
    
    $socket = @stream_socket_client(
        $connection_string,
        $errno,
        $errstr,
        10,
        STREAM_CLIENT_CONNECT,
        $context
    );
    
    if ($socket) {
        $result['success'] = true;
        $result['message'] = "成功建立 {$crypto_method} 连接到 {$host}:{$port}";
        
        // 获取证书信息
        $cert = stream_context_get_params($socket);
        if (isset($cert['options']['ssl']['peer_certificate'])) {
            $cert_info = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);
            $result['certificate_info'] = [
                'subject' => $cert_info['subject']['CN'] ?? 'Unknown',
                'issuer' => $cert_info['issuer']['CN'] ?? 'Unknown',
                'valid_from' => date('Y-m-d H:i:s', $cert_info['validFrom_time_t']),
                'valid_to' => date('Y-m-d H:i:s', $cert_info['validTo_time_t'])
            ];
        }
        
        fclose($socket);
    } else {
        $result['message'] = "无法建立 {$crypto_method} 连接到 {$host}:{$port} - {$errstr} ({$errno})";
    }
    
    return $result;
}

/**
 * DNS解析测试
 */
function nenghui_test_dns_resolution($host) {
    $result = [
        'success' => false,
        'message' => '',
        'ip_addresses' => []
    ];
    
    // 测试DNS解析
    $ip_addresses = @gethostbynamel($host);
    
    if ($ip_addresses && !empty($ip_addresses)) {
        $result['success'] = true;
        $result['ip_addresses'] = $ip_addresses;
        $result['message'] = "✅ DNS解析成功: {$host} → " . implode(', ', $ip_addresses);
    } else {
        $result['message'] = "❌ DNS解析失败: 无法解析域名 {$host}";
        $result['message'] .= "\n🔍 可能的原因:\n";
        $result['message'] .= "• DNS服务器配置问题\n";
        $result['message'] .= "• 域名不存在或已过期\n";
        $result['message'] .= "• 网络连接问题\n";
    }
    
    return $result;
}

/**
 * 网络连通性测试
 */
function nenghui_test_network_connectivity() {
    $result = [
        'success' => false,
        'message' => '',
        'tests' => []
    ];
    
    // 测试常见的公共DNS服务器
    $test_hosts = [
        '8.8.8.8' => 'Google DNS',
        '114.114.114.114' => '114 DNS',
        '223.5.5.5' => '阿里DNS'
    ];
    
    $successful_tests = 0;
    
    foreach ($test_hosts as $ip => $name) {
        $start_time = microtime(true);
        $socket = @fsockopen($ip, 53, $errno, $errstr, 5);
        $end_time = microtime(true);
        $time = round(($end_time - $start_time) * 1000, 2);
        
        if ($socket) {
            $result['tests'][] = "✅ {$name} ({$ip}): 连接成功 ({$time}ms)";
            $successful_tests++;
            fclose($socket);
        } else {
            $result['tests'][] = "❌ {$name} ({$ip}): 连接失败 - {$errstr}";
        }
    }
    
    if ($successful_tests > 0) {
        $result['success'] = true;
        $result['message'] = "✅ 网络连通性正常 ({$successful_tests}/" . count($test_hosts) . " 测试通过)";
    } else {
        $result['message'] = "❌ 网络连通性异常 (所有测试都失败)";
        $result['message'] .= "\n🔍 可能的原因:\n";
        $result['message'] .= "• 服务器网络连接问题\n";
        $result['message'] .= "• 防火墙阻止了出站连接\n";
        $result['message'] .= "• DNS服务配置问题\n";
    }
    
    return $result;
}

/**
 * 运行完整的SMTP诊断
 */
function nenghui_run_smtp_diagnostic() {
    if (!current_user_can('manage_options')) {
        wp_die('权限不足');
    }
    
    $smtp_host = get_option('nenghui_smtp_host');
    $smtp_port = get_option('nenghui_smtp_port', '587');
    $smtp_secure = get_option('nenghui_smtp_secure', 'tls');
    
    $diagnostic_results = [];
    
    // 1. 系统环境检查
    $diagnostic_results['system'] = nenghui_get_smtp_diagnostic_info();
    
    // 2. 网络连通性测试
    $diagnostic_results['network'] = nenghui_test_network_connectivity();
    
    // 3. DNS解析测试
    if (!empty($smtp_host)) {
        $diagnostic_results['dns'] = nenghui_test_dns_resolution($smtp_host);
        
        // 4. 端口连接测试
        $diagnostic_results['port_test'] = nenghui_test_port_connection($smtp_host, $smtp_port);
        
        // 5. SSL/TLS连接测试
        if ($smtp_secure !== 'none') {
            $diagnostic_results['ssl_test'] = nenghui_test_ssl_connection($smtp_host, $smtp_port, $smtp_secure);
        }
    }
    
    // 显示诊断结果
    add_action('admin_notices', function() use ($diagnostic_results) {
        $output = '<div class="notice notice-info is-dismissible">';
        $output .= '<h3>SMTP诊断报告</h3>';
        
        // 系统环境
        $output .= '<h4>系统环境</h4>';
        $output .= '<ul>';
        $output .= '<li>PHP版本: ' . esc_html($diagnostic_results['system']['php_version']) . '</li>';
        
        foreach ($diagnostic_results['system']['extensions'] as $ext => $loaded) {
            $status = $loaded ? '✓' : '✗';
            $color = $loaded ? 'green' : 'red';
            $output .= '<li style="color: ' . $color . ';">扩展 ' . $ext . ': ' . $status . '</li>';
        }
        
        if (isset($diagnostic_results['system']['openssl_version'])) {
            $output .= '<li>OpenSSL版本: ' . esc_html($diagnostic_results['system']['openssl_version']) . '</li>';
        }
        
        $output .= '</ul>';
        
        // 网络连通性测试
        if (isset($diagnostic_results['network'])) {
            $output .= '<h4>网络连通性测试</h4>';
            $color = $diagnostic_results['network']['success'] ? 'green' : 'red';
            $output .= '<p style="color: ' . $color . ';">' . nl2br(esc_html($diagnostic_results['network']['message'])) . '</p>';
            
            if (!empty($diagnostic_results['network']['tests'])) {
                $output .= '<ul>';
                foreach ($diagnostic_results['network']['tests'] as $test) {
                    $output .= '<li>' . esc_html($test) . '</li>';
                }
                $output .= '</ul>';
            }
        }
        
        // DNS解析测试
        if (isset($diagnostic_results['dns'])) {
            $output .= '<h4>DNS解析测试</h4>';
            $color = $diagnostic_results['dns']['success'] ? 'green' : 'red';
            $output .= '<p style="color: ' . $color . ';">' . nl2br(esc_html($diagnostic_results['dns']['message'])) . '</p>';
            
            if (!empty($diagnostic_results['dns']['ip_addresses'])) {
                $output .= '<p><strong>解析到的IP地址:</strong></p>';
                $output .= '<ul>';
                foreach ($diagnostic_results['dns']['ip_addresses'] as $ip) {
                    $output .= '<li>' . esc_html($ip) . '</li>';
                }
                $output .= '</ul>';
            }
        }
        
        // 端口连接测试
        if (isset($diagnostic_results['port_test'])) {
            $output .= '<h4>端口连接测试</h4>';
            $color = $diagnostic_results['port_test']['success'] ? 'green' : 'red';
            $output .= '<p style="color: ' . $color . ';">' . nl2br(esc_html($diagnostic_results['port_test']['message'])) . '</p>';
        }
        
        // SSL/TLS连接测试
        if (isset($diagnostic_results['ssl_test'])) {
            $output .= '<h4>SSL/TLS连接测试</h4>';
            $color = $diagnostic_results['ssl_test']['success'] ? 'green' : 'red';
            $output .= '<p style="color: ' . $color . ';">' . esc_html($diagnostic_results['ssl_test']['message']) . '</p>';
            
            if ($diagnostic_results['ssl_test']['certificate_info']) {
                $cert = $diagnostic_results['ssl_test']['certificate_info'];
                $output .= '<p><strong>证书信息:</strong></p>';
                $output .= '<ul>';
                $output .= '<li>主题: ' . esc_html($cert['subject']) . '</li>';
                $output .= '<li>颁发者: ' . esc_html($cert['issuer']) . '</li>';
                $output .= '<li>有效期: ' . esc_html($cert['valid_from']) . ' 至 ' . esc_html($cert['valid_to']) . '</li>';
                $output .= '</ul>';
            }
        }
        
        $output .= '</div>';
        echo $output;
    });
}

// 处理诊断请求
if (isset($_GET['nenghui_smtp_diagnostic']) && $_GET['nenghui_smtp_diagnostic'] === '1') {
    add_action('admin_init', 'nenghui_run_smtp_diagnostic');
}

?>