<?php

declare(strict_types=1);


namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Queue\Worker as QueueWorker;
use Illuminate\Queue\WorkerOptions;
use Illuminate\Support\Facades\Log;
use Workerman\Connection\TcpConnection;
use Workerman\Timer;
use Workerman\Worker;

class WorkermanServe extends Command
{
    protected $signature = 'workerman:serve {action=start : start/stop/restart/reload}';

    protected $description = '启动 Workerman 常驻服务：队列消费者（database/redis）+ WebSocket 进度推送';

    public function handle(): int
    {
        Worker::$pidFile = storage_path('framework/workerman.pid');

        $this->info('Workerman 启动中（'.config('workerman.name').'）...');

        // 队列消费者：复用 Laravel 队列 Worker（database / redis 统一支持），
        // 常驻进程内框架只启动一次，省去每个任务的启动开销
        $queueWorker = new Worker();
        $queueWorker->name = 'laralog-queue';
        $queueWorker->count = (int) config('workerman.queue_workers', 2);
        $queueWorker->onWorkerStart = function ($worker) {
            $this->info("队列消费者 {$worker->id} 启动（连接：".config('workerman.queue_connection').'，队列：'.config('workerman.queues').'）');
            Timer::add(1, function () {
                try {
                    $this->consumeNextJob();
                } catch (\Throwable $e) {
                    Log::error('Workerman 任务执行失败', ['error' => $e->getMessage()]);
                }
            });
        };

        // WebSocket：向后台推送任务进度
        $ws = new Worker('websocket://'.config('workerman.websocket_host', '0.0.0.0').':'.config('workerman.websocket_port', 8787));
        $ws->name = 'laralog-ws';
        $ws->onConnect = function (TcpConnection $connection) {
            \App\Blog\Support\WorkermanBroadcaster::add($connection);
            $connection->send(json_encode(['event' => 'connected']));
        };
        $ws->onClose = fn (TcpConnection $connection) => \App\Blog\Support\WorkermanBroadcaster::remove($connection);

        Worker::runAll();

        return self::SUCCESS;
    }

    /**
     * 消费一个任务。使用 Laravel 队列 Worker：
     * - 支持 database / redis 等所有驱动（redis 的 reserved/重试/超时语义由驱动处理）
     * - sleep=0 避免阻塞 Workerman event loop（由 1s Timer 驱动轮询）
     * - 任务 handle() 的依赖（如 LlmClient）由容器自动注入
     */
    private function consumeNextJob(): void
    {
        $connection = (string) config('workerman.queue_connection', config('queue.default'));
        // Worker 内部按逗号分隔解析多队列（如 "default,ai"）
        $queues = (string) config('workerman.queues', 'default');
        $queues = $queues === '' ? 'default' : $queues;

        $worker = new QueueWorker(
            app('queue'),
            app('events'),
            app(ExceptionHandler::class),
            fn () => app()->isDownForMaintenance(),
        );

        $options = new WorkerOptions(
            name: 'laralog',
            backoff: 0,
            memory: 128,
            timeout: (int) config('workerman.timeout', 60),
            sleep: 0,
            maxTries: (int) config('workerman.max_tries', 3),
        );

        $worker->runNextJob($connection, $queues, $options);
    }
}
