<?php

/**
 * 文件功能：投放神秘箱子队列任务
 *
 * 由调度器或管理员手动触发，执行以下操作：
 * 1. 创建神秘箱记录（含暗号、类型、奖励范围）
 * 2. 公屏广播暗号提示（全服可见）
 * 3. 设定定时关闭任务（windows_seconds 秒后过期）
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Jobs;

use App\Events\MessageSent;
use App\Models\GameConfig;
use App\Models\MysteryBox;
use App\Services\ChatStateService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Str;

class DropMysteryBoxJob implements ShouldQueue
{
    use Queueable;

    /**
     * 最大重试次数。
     */
    public int $tries = 1;

    /**
     * @param  string  $boxType  箱子类型：normal | rare | trap
     * @param  int|null  $roomId  投放目标房间，null 时默认 1
     * @param  string|null  $passcode  手动指定暗号（null=自动生成）
     * @param  int|null  $droppedBy  投放者用户ID（null=系统自动）
     */
    public function __construct(
        public readonly string $boxType = 'normal',
        public readonly ?int $roomId = 1,
        public readonly ?string $passcode = null,
        public readonly ?int $droppedBy = null,
    ) {}

    /**
     * 执行投放逻辑。
     */
    public function handle(ChatStateService $chatState): void
    {
        // 检查游戏是否开启
        if (! GameConfig::isEnabled('mystery_box')) {
            return;
        }

        $config = GameConfig::forGame('mystery_box')?->params ?? [];
        $claimWindow = (int) ($config['claim_window_seconds'] ?? 120);
        $targetRoom = $this->roomId ?? 1;

        // 自动生成随机暗号（若未指定）
        $passcode = $this->passcode ?? strtoupper(Str::random(6));

        // 根据类型确定奖励范围
        [$rewardMin, $rewardMax] = match ($this->boxType) {
            'rare' => [
                (int) ($config['rare_reward_min'] ?? 5000),
                (int) ($config['rare_reward_max'] ?? 20000),
            ],
            'trap' => [
                (int) ($config['trap_penalty_min'] ?? 200),
                (int) ($config['trap_penalty_max'] ?? 1000),
            ],
            default => [
                (int) ($config['normal_reward_min'] ?? 500),
                (int) ($config['normal_reward_max'] ?? 2000),
            ],
        };

        // 创建箱子记录
        $box = MysteryBox::create([
            'box_type' => $this->boxType,
            'passcode' => $passcode,
            'reward_min' => $rewardMin,
            'reward_max' => $rewardMax,
            'status' => 'open',
            'expires_at' => now()->addSeconds($claimWindow),
            'dropped_by' => $this->droppedBy,
        ]);

        // 公屏广播暗号提示
        $emoji = $box->typeEmoji();
        $typeName = $box->typeName();
        $source = $this->droppedBy ? '管理员' : '系统';

        $content = "{$emoji}【神秘箱子】《{$typeName}》{$source}投放了一个神秘箱子！"
            ."发送暗号「{$passcode}」即可开箱！限时 {$claimWindow} 秒，先到先得！";

        $msg = [
            'id' => $chatState->nextMessageId($targetRoom),
            'room_id' => $targetRoom,
            'from_user' => '系统传音',
            'to_user' => '大家',
            'content' => $content,
            'is_secret' => false,
            'font_color' => match ($this->boxType) {
                'rare' => '#c4b5fd',
                'trap' => '#f87171',
                default => '#34d399',
            },
            'action' => '大声宣告',
            'sent_at' => now()->toDateTimeString(),
        ];

        $chatState->pushMessage($targetRoom, $msg);
        broadcast(new MessageSent($targetRoom, $msg));
        SaveMessageJob::dispatch($msg);

        // 定时关闭任务：到期后将箱子标记为 expired
        ExpireMysteryBoxJob::dispatch($box->id)->delay(now()->addSeconds($claimWindow + 5));
    }
}
