<?php

namespace App\Http\Requests;

use App\Services\NewCarBulkUpdateService;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;

class NewCarBulkUpdateRequest extends FormRequest
{
    private ?array $allowedFields = null;

    public function authorize(): bool
    {
        return Auth::check();
    }

    public function rules(): array
    {
        $allowedFields = $this->getAllowedFields();

        return [
            'mode' => ['required', 'string', Rule::in(['same', 'different'])],
            'version_action' => ['nullable', 'string', Rule::in(['publish', 'draft'])],
            'new_car_ids' => ['required', 'array', 'max:100'],
            'new_car_ids.*' => ['required', 'integer', 'exists:new_cars,id'],

            // Same mode validation
            'field' => [
                'required_if:mode,same',
                'nullable',
                'string',
                Rule::in($allowedFields),
            ],
            'value' => ['required_if:mode,same', 'nullable'],

            // Different mode validation
            'updates' => ['required_if:mode,different', 'nullable', 'array'],
            'updates.*' => ['array'],
            'updates.*.*' => ['nullable'],
        ];
    }

    public function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            if ($this->input('mode') === 'different') {
                $this->validateDifferentModeUpdates($validator);
            }
        });
    }

    private function validateDifferentModeUpdates($validator): void
    {
        $updates = $this->input('updates', []);
        $newCarIds = $this->input('new_car_ids', []);
        $allowedFields = $this->getAllowedFields();

        foreach ($updates as $newCarId => $fields) {
            if (!in_array((int) $newCarId, array_map('intval', $newCarIds))) {
                $validator->errors()->add(
                    "updates.{$newCarId}",
                    "New car ID {$newCarId} is not in the selected new cars list."
                );
                continue;
            }

            if (!is_array($fields)) {
                continue;
            }

            foreach (array_keys($fields) as $field) {
                if (!in_array($field, $allowedFields)) {
                    $validator->errors()->add(
                        "updates.{$newCarId}.{$field}",
                        "Field '{$field}' is not allowed for bulk update."
                    );
                }
            }
        }
    }

    private function getAllowedFields(): array
    {
        if ($this->allowedFields === null) {
            $service = app(NewCarBulkUpdateService::class);
            $this->allowedFields = $service->getAllowedFields();
        }

        return $this->allowedFields;
    }

    public function messages(): array
    {
        return [
            'mode.required' => 'Please select an update mode.',
            'mode.in' => 'Invalid update mode. Must be "same" or "different".',
            'new_car_ids.required' => 'Please select at least one new car.',
            'new_car_ids.max' => 'You can only update up to 100 new cars at a time.',
            'new_car_ids.*.exists' => 'One or more selected new cars do not exist.',
            'field.required_if' => 'Please select a field to update.',
            'field.in' => 'The selected field is not allowed for bulk update.',
            'value.required_if' => 'Please provide a value for the selected field.',
            'updates.required_if' => 'Please provide updates for the selected new cars.',
        ];
    }
}
