<?php







if (PHP_SAPI !== 'cli') {
    http_response_code(404);
    exit(1);
}

ignore_user_abort(true);
ini_set('display_errors', '0');
ini_set('log_errors', '1');

define('DS', DIRECTORY_SEPARATOR);
$root = dirname(__DIR__);

if (!is_file($root . DS . 'config.php')) {
    exit(1);
}

require_once $root . DS . 'core' . DS . 'runtime_reader_lock.php';
$easychat_runtime_reader_lock = easychat_runtime_reader_lock_acquire($root, false);

if (is_file($root . DS . 'version.php')) {
    require_once $root . DS . 'version.php';
}
if (!defined('EASYCHAT_VERSION')) {
    define('EASYCHAT_VERSION', '1.0.0');
}

require_once $root . DS . 'library' . DS . 'request_context.php';
\EasyChat\Library\RequestContext::bootstrapServerDefaults([
    'HTTP_HOST' => 'localhost',
    'SCRIPT_NAME' => '/cli/max_polling.php',
    'HTTPS' => 'off',
    'HTTP_X_FORWARDED_PROTO' => '',
    'HTTP_X_FORWARDED_SSL' => '',
    'SERVER_PORT' => 80,
]);

require_once $root . DS . 'config.php';
if (!defined('DB_DATABASE') || DB_DATABASE === '') {
    exit(1);
}

require_once SITE_PATH . DS . 'core' . DS . 'autoload.php';

function easychat_max_polling_connection_error_message(Throwable $e): string {
    return str_replace(['<br />', '<br>', '<br/>'], ' ', $e->getMessage());
}

function easychat_max_polling_is_transient_db_connection_error(Throwable $e): bool {
    $message = $e->getMessage();
    return strpos($message, 'Error No: 2002') !== false
        || strpos($message, 'Error No: 1040') !== false
        || strpos($message, 'Error No: 2006') !== false
        || strpos($message, 'Error No: 2013') !== false
        || stripos($message, 'Connection refused') !== false
        || stripos($message, 'Too many connections') !== false
        || stripos($message, 'server has gone away') !== false
        || stripos($message, 'lost connection') !== false;
}

function easychat_max_polling_connect_db_with_retry() {
    $attempts = 3;
    $last_exception = null;

    for ($attempt = 1; $attempt <= $attempts; $attempt++) {
        try {
            return new DB(DB_DRIVER, DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE, DB_PORT);
        } catch (Throwable $e) {
            $last_exception = $e;
            if (!easychat_max_polling_is_transient_db_connection_error($e) || $attempt >= $attempts) {
                throw $e;
            }
            usleep(250000 * $attempt);
        }
    }

    throw $last_exception ?: new RuntimeException('unknown_db_connection_error');
}

try {
    $registry = new Registry();
    $db = easychat_max_polling_connect_db_with_retry();
    $registry->set('db', $db);
    (new EasyChat\Library\AppClock($registry))->syncDatabaseSessionTimezone();
    if (class_exists('EasyChat_Install_Service')) {
        EasyChat_Install_Service::ensureRuntimeSchema($db, easychat_db_prefix());
        EasyChat\Library\AppClock::resetTimezoneCache();
        (new EasyChat\Library\AppClock($registry))->syncDatabaseSessionTimezone();
    }

    $heartbeat = new EasyChat\Library\Messenger\MaxCronHeartbeatRepository($registry);
    $heartbeat_run_id = $heartbeat->start();
    $heartbeat_started_at = microtime(true);
    try {
        $service = new EasyChat\Library\Messenger\MaxPollingService($registry);
        $result = $service->run([
            'source' => 'dedicated_cron',
        ]);
        $success = !empty($result['success']);
        $exit_code = $success ? 0 : 1;
        $heartbeat->finish(
            $heartbeat_run_id,
            $success,
            $exit_code,
            (int)round((microtime(true) - $heartbeat_started_at) * 1000)
        );
        exit($exit_code);
    } catch (Throwable $e) {
        $heartbeat->finish(
            $heartbeat_run_id,
            false,
            1,
            (int)round((microtime(true) - $heartbeat_started_at) * 1000)
        );
        throw $e;
    }
} catch (Throwable $e) {
    fwrite(STDERR, 'MAX polling failed: ' . easychat_max_polling_connection_error_message($e) . PHP_EOL);
    exit(1);
}
