<?php

/**
 * 文件功能：保存游戏参数请求校验
 *
 * 统一校验后台“游戏管理”页提交的 params 结构，
 * 并在所有游戏共用的房间范围字段上执行归一化。
 */

namespace App\Http\Requests;

use App\Services\GameRoomScopeService;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;

/**
 * 类功能：约束后台游戏参数保存请求的公共结构。
 */
class UpdateGameConfigParamsRequest extends FormRequest
{
    /**
     * 判断当前请求是否允许执行。
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * 校验规则。
     *
     * @return array<string, ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'params' => ['required', 'array'],
            'params.room_scope_mode' => ['nullable', 'in:all,single,multiple'],
            'params.room_ids' => ['nullable', 'array'],
            'params.room_ids.*' => ['integer', 'exists:rooms,id'],
        ];
    }

    /**
     * 自定义错误消息。
     *
     * @return array<string, string>
     */
    public function messages(): array
    {
        return [
            'params.required' => '缺少游戏参数数据。',
            'params.array' => '游戏参数格式无效。',
            'params.room_scope_mode.in' => '参与房间模式无效。',
            'params.room_ids.array' => '参与房间列表格式无效。',
            'params.room_ids.*.integer' => '参与房间编号格式无效。',
            'params.room_ids.*.exists' => '所选房间不存在，请刷新页面后重试。',
        ];
    }

    /**
     * 在校验前先把房间范围字段归一化，兼容单值与旧字段。
     */
    protected function prepareForValidation(): void
    {
        $params = (array) $this->input('params', []);
        $roomScopeService = app(GameRoomScopeService::class);
        $scopeConfig = $roomScopeService->getScopeConfigForParams($params);

        $params['room_scope_mode'] = $scopeConfig['room_scope_mode'];
        $params['room_ids'] = $scopeConfig['room_ids'];

        $this->merge([
            'params' => $params,
        ]);
    }

    /**
     * 校验通过后补充“单选/多选至少选择一个房间”的约束。
     */
    public function withValidator($validator): void
    {
        $validator->after(function ($validator): void {
            $params = (array) $this->input('params', []);
            $roomMode = (string) ($params['room_scope_mode'] ?? GameRoomScopeService::MODE_SINGLE);
            $roomIds = (array) ($params['room_ids'] ?? []);

            if (in_array($roomMode, [GameRoomScopeService::MODE_SINGLE, GameRoomScopeService::MODE_MULTIPLE], true) && $roomIds === []) {
                $validator->errors()->add('params.room_ids', '单选/多选房间模式下，请至少选择一个房间。');
            }

            if ($roomMode === GameRoomScopeService::MODE_SINGLE && count($roomIds) > 1) {
                $validator->errors()->add('params.room_ids', '单选房间模式下只能选择一个房间。');
            }
        });
    }
}
