<?php

/**
 * 文件功能：红包领取成功广播事件（广播至房间与领取者私有频道）
 *
 * 触发时机：RedPacketController::claim() 成功后广播，
 * 房间内在线用户收到后实时刷新剩余份数，领取者本人可同步收到到账提示。
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

/**
 * 类功能：广播礼包被领取后的实时状态
 *
 * 统一向房间频道推送剩余份数变化，同时向领取者私有频道推送到账结果，
 * 让红包弹窗与用户提示保持一致。
 */
class RedPacketClaimed implements ShouldBroadcastNow
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * @param  User  $claimer  领取用户
     * @param  int  $amount  领取金额
     * @param  int  $envelopeId  红包 ID
     * @param  int  $roomId  房间 ID
     * @param  int  $remainingCount  剩余份数
     * @param  string  $type  红包类型
     */
    public function __construct(
        public readonly User $claimer,
        public readonly int $amount,
        public readonly int $envelopeId,
        public readonly int $roomId,
        public readonly int $remainingCount,
        public readonly string $type = 'gold',
    ) {}

    /**
     * 广播至房间频道与领取者私有频道。
     *
     * @return array<int, \Illuminate\Broadcasting\Channel>
     */
    public function broadcastOn(): array
    {
        return [
            new PresenceChannel('room.'.$this->roomId),
            new PrivateChannel('user.'.$this->claimer->id),
        ];
    }

    /**
     * 广播领取结果与剩余份数。
     *
     * @return array<string, mixed>
     */
    public function broadcastWith(): array
    {
        $typeLabel = $this->type === 'exp' ? '经验' : '金币';

        return [
            'envelope_id' => $this->envelopeId,
            'claimer_id' => $this->claimer->id,
            'claimer_username' => $this->claimer->username,
            'amount' => $this->amount,
            'remaining_count' => $this->remainingCount,
            'type' => $this->type,
            'message' => "🧧 成功抢到 {$this->amount} {$typeLabel}礼包！",
        ];
    }

    /** 广播事件名称。 */
    public function broadcastAs(): string
    {
        return 'red-packet.claimed';
    }
}
