<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

/**
 * 界面文档 §2.1：`draw.countdown`
 *
 * 每秒由 `lottery:hall-countdown` 命令派发。使用专用队列 `broadcasts:countdown`
 * 与低频广播隔离，并配置短超时 + 单次尝试，避免队列积压时广播过期数据。
 */
final class DrawCountdownBroadcast implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * 专用倒计时队列，与常规广播队列 `broadcasts` 隔离，
     * 避免低频事件阻塞高频 countdown 任务。
     */
    public string $queue = 'broadcasts:countdown';

    /**
     * 单次尝试：倒计时数据时效性极高，失败后重试已无意义。
     */
    public int $tries = 1;

    /**
     * 单任务超时 5 秒：广播本身应在 1s 内完成，超时说明 Reverb 连接异常。
     */
    public int $timeout = 5;

    /**
     * 从派发起 5 秒内必须开始执行，否则队列工作者自动丢弃。
     * 防止队列积压时大量过期 countdown 事件被顺序处理。
     */
    public function retryUntil(): \DateTimeInterface
    {
        return now()->addSeconds(5);
    }

    /**
     * @param  array<string, mixed>|null  $data  与 GET draw/current 的 data 相同
     */
    public function __construct(
        public readonly ?array $data,
        public readonly int $emittedAtMs,
    ) {}

    /** @return array<int, Channel> */
    public function broadcastOn(): array
    {
        return [new Channel('lottery-hall')];
    }

    public function broadcastAs(): string
    {
        return 'draw.countdown';
    }

    /** @return array{data: array<string, mixed>|null, emitted_at_ms: int} */
    public function broadcastWith(): array
    {
        return [
            'data' => $this->data,
            'emitted_at_ms' => $this->emittedAtMs,
        ];
    }
}
