<?php
/** 只读部署诊断：不输出密码、密钥、OpenID、token 或 SQL 原文。 */
if (PHP_SAPI !== 'cli') { http_response_code(404); exit; }
$failed = false;
function chatCheck($label, $callback) {
    global $failed;
    try {
        $result = $callback();
        if ($result === false) throw new RuntimeException('check failed');
        echo '[OK] '.$label.(is_string($result) ? ': '.$result : '').PHP_EOL;
        return $result;
    } catch (\Throwable $error) {
        $failed = true;
        $driver = 0;
        if ($error instanceof \think\db\exception\PDOException) {
            $info = $error->getData(); $driver = (int)($info['PDO Error Info']['Driver Error Code'] ?? 0);
        } elseif ($error instanceof \PDOException) $driver = (int)($error->errorInfo[1] ?? 0);
        echo '[FAIL] '.$label.'; type='.get_class($error).'; driver='.$driver.PHP_EOL;
        return false;
    }
}
$root = dirname(__DIR__);
if (!chatCheck('ThinkPHP autoload', function () use ($root) { return is_file($root.'/vendor/autoload.php'); })) exit(1);
require $root.'/vendor/autoload.php';
$app = chatCheck('Application initialization', function () use ($root) { $app = new \think\App($root.'/'); $app->initialize(); return $app; });
if (!$app) exit(1);
chatCheck('config/chat.php exists', function () use ($root) { return is_file($root.'/config/chat.php'); });
chatCheck('ChatService class', function () { return class_exists(\app\mobile\service\ChatService::class); });
chatCheck('Workerman autoload', function () use ($root) { return is_file($root.'/scripts/chat-realtime/vendor/autoload.php'); });
chatCheck('socket_listen', function () use ($app) { $value = $app->config->get('chat.socket_listen'); return is_string($value) && preg_match('#^websocket://[^/]+:[0-9]+$#', $value) ? $value : false; });
chatCheck('socket_url', function () use ($app) { $value = $app->config->get('chat.socket_url'); return is_string($value) && strpos($value,'wss://')===0 ? $value : false; });
chatCheck('WeChat secret configured (value hidden)', function () use ($app) { return (bool)$app->config->get('chat.secret'); });
chatCheck('Redis PHP extension', function () { return extension_loaded('redis'); });
chatCheck('Redis connection', function () { return \think\facade\Cache::store('redis')->handler()->ping() !== false; });
$connection = $app->config->get('database.connections.'.$app->config->get('database.default'), []);
echo 'Global connection charset: '.($connection['charset'] ?? '(not configured)').PHP_EOL;
if (!chatCheck('Chat request charset initialization', function () use ($app) { \app\mobile\service\ChatService::useChatCharset($app); return true; })) exit(1);
echo 'Database: '.($connection['database'] ?? '(not configured)').'; prefix: '.($connection['prefix'] ?? '(not configured)').PHP_EOL;
$dbReady = chatCheck('MySQL connection', function () { \think\facade\Db::query('SELECT 1'); return true; });
if ($dbReady) {
    chatCheck('MySQL connection charset utf8mb4 (emoji support)', function () {
        $row=\think\facade\Db::query('SELECT @@character_set_client AS charset');
        return ($row[0]['charset'] ?? '') === 'utf8mb4';
    });
    $prefix = $connection['prefix'] ?? '';
    if (!preg_match('/^[a-zA-Z0-9_]*$/', $prefix)) { echo '[FAIL] Invalid table prefix'.PHP_EOL; $failed = true; }
    else {
        $tables = ['chat_room'=>['expires_at','closed_at','reminder_stage','version'],'chat_member'=>['status','last_read','last_mention','attention'],'chat_message'=>['revision','created_at'],'chat_invite'=>['expires_at'],'chat_image'=>['path'],'chat_report'=>['status'],'chat_log'=>['created_at']];
        foreach ($tables as $table=>$fields) {
            $actual = chatCheck('Table '.$prefix.$table, function () use ($prefix,$table) { return \think\facade\Db::query('SHOW COLUMNS FROM `'.$prefix.$table.'`'); });
            if ($actual !== false) {
                $present = array_column($actual,'Field');
                foreach ($fields as $field) chatCheck($table.'.'.$field, function () use ($present,$field) { return in_array($field,$present,true); });
                if($table==='chat_message')chatCheck('chat_message.content utf8mb4',function()use($prefix){
                    $columns=\think\facade\Db::query('SHOW FULL COLUMNS FROM `'.$prefix.'chat_message`');
                    foreach($columns as$column)if($column['Field']==='content')return strpos((string)$column['Collation'],'utf8mb4_')===0;
                    return false;
                });
            }
        }
        chatCheck('Public hall initialized', function () { $room = \think\facade\Db::name('chat_room')->find(1); return $room && (int)$room['owner_id']===0; });
    }
}
echo $failed ? "RESULT: failed. Fix [FAIL] items before starting the worker.\n" : "RESULT: configuration, Redis and database checks passed.\n";
exit($failed ? 1 : 0);
