#!/usr/bin/env php
<?php
/** For Swoole coroutine tests */

// 如果改成 true，则会在终端显示所有炸毛框架的 Log
const ZM_TEST_LOG_DEBUG = false;

use OneBot\Driver\Event\Process\WorkerStartEvent;
use PHPUnit\TextUI\Command;
use Swoole\Atomic;
use Tests\ZMResultPrinter;
use ZM\Command\Server\ServerStartCommand;
use ZM\Event\EventProvider;
use ZM\Framework;
use ZM\Logger\ConsoleLogger;
use ZM\Store\MockAtomic;

// 引入自动加载
require $_composer_autoload_path ?? dirname(__DIR__) . '/vendor/autoload.php';

// 声明一个全局的原子计数，用于保存整个进程的退出状态码
global $_swoole_atomic;
// Windows 没有 Swoole，所以就使用了一个假的原子计数器，反正 Windows 只有单进程
$_swoole_atomic = class_exists('\\Swoole\\Atomic') ? new Atomic() : new MockAtomic();

// 注册 Logger 等级
ob_logger_register(new ConsoleLogger(ZM_TEST_LOG_DEBUG ? 'debug' : 'error'));

// 使用框架自身的 EventProvider
global $ob_event_provider;
$ob_event_provider = new EventProvider();

// 注册一个最低级别的 WorkerStart 事件，用于在框架的事件初始化之后开始运行 PHPUnit
ob_event_provider()->addEventListener(WorkerStartEvent::getName(), function () {
    register_shutdown_function(function () {
        $error = error_get_last();
        // 下面这段代码的作用就是，不是错误引发的退出时照常退出即可
        if (($error['type'] ?? 0) != 0) {
            logger()->emergency(zm_internal_errcode('E00027') . 'Internal fatal error: ' . $error['message'] . ' at ' . $error['file'] . "({$error['line']})");
        }
        Framework::getInstance()->stop();
    });
    $_SERVER['argv'][] = '--printer';
    $_SERVER['argv'][] = ZMResultPrinter::class;
    try {
        // 不退出，而是返回 code
        $retcode = Command::main(false);
    } finally {
        global $_swoole_atomic;
        $_swoole_atomic->set($retcode ?? 0);
        Framework::getInstance()->stop($retcode ?? 0);
    }
}, 1);

try {
    $options = ServerStartCommand::exportOptionArray();
    $options['driver'] = 'workerman';
    $options['worker-num'] = 1;
    $options['private-mode'] = true;
    (new Framework($options))->init()->start();
    exit($_swoole_atomic->get());
} catch (Throwable $e) {
    echo $e->getMessage() . PHP_EOL;
    exit(1);
}
