<?php

namespace App\Http\Requests\Api\V1\Booking;

use App\Models\Game;
use App\Models\Member;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;

class StoreBookingRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function participants(): array
    {
        $participants = $this->input('participants');

        if (is_string($participants)) {
            $participants = json_decode($participants, true) ?? [];
        }

        return is_array($participants) ? $participants : [];
    }

    public function rules(): array
    {
        return [
            'game_id'      => ['required', 'integer', 'exists:games,id'],
            'booking_date' => ['required', 'date', 'date_format:Y-m-d', 'after_or_equal:today'],
            'start_time'   => ['required', 'date_format:H:i'],
            'participants' => ['required', 'array', 'min:1'],
            'participants.*.identifier' => ['required', 'string'],
        ];
    }

    public function messages(): array
    {
        return [
            'booking_date.after_or_equal' => __('Cannot book for past dates.'),
            'participants.array'          => __('Participants must be an array of objects with identifier.'),
            'participants.*.identifier.required' => __('Each participant must have an identifier.'),
        ];
    }

    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator) {
            $member = $this->user();
            if (! $member instanceof Member) {
                $validator->errors()->add('member', __('Invalid member.'));
                return;
            }


            if (!$member->canBook()) {
                $validator->errors()->add('member', __('You must be an active member with valid subscription to book.'));
                return;
            }

            $game = Game::find($this->game_id);
            if (! $game || $game->status !== 1) {
                $validator->errors()->add('game_id', __('Selected game is not available.'));
                return;
            }

            $participantIds = collect($this->participants())->map(function ($p) use ($validator) {
                $identifier = $p['identifier'] ?? null;
                if (! $identifier || ! is_string($identifier)) {
                    $validator->errors()->add('participants', __('Invalid participant identifier.'));
                    return null;
                }

                $member = Member::where('phone', $identifier)
                    ->orWhere('qr_code', $identifier)
                    ->orWhereRaw('UPPER(TRIM(qr_code_static)) = ?', [strtoupper(trim($identifier))])
                    ->first();

                if (! $member) {
                    $validator->errors()->add('participants', __("Member with identifier {$identifier} not found."));
                }

                return $member?->id;
            })->filter()->values();

            $count = $participantIds->count();


            if ($count < $game->min_players - 1) {
                $validator->errors()->add('participants', __('Minimum :min players required for this game.', ['min' => $game->min_players]));
            }

            if ($count > $game->max_players) {
                $validator->errors()->add('participants', __('Maximum :max players allowed for this game.', ['max' => $game->max_players]));
            }

            if ($participantIds->count() !== $participantIds->unique()->count()) {
                $validator->errors()->add('participants', __('Duplicate participants are not allowed.'));
            }
        });
    }

    protected function failedValidation(Validator $validator): void
    {
        throw new HttpResponseException(
            response()->json([
                'message' => __('Validation failed'),
                'status'  => false,
                'errors'  => $validator->errors(),
            ], 422)
        );
    }
}
