<?php

namespace Maestro\Core\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;

/**
 * Validation for DataTable export: same shape as fetch (filters, sort, visibleColumns, columnOrder, globalSearch)
 * but without pagination. Used by POST /api/datatables/{resourceKey}/export.
 */
class ExportDataTableRequest extends FormRequest
{
    private const MAX_PAYLOAD_BYTES = 51200; // 50KB

    public function authorize(): bool
    {
        return $this->user() !== null;
    }

    /**
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'tableKey' => ['nullable', 'string', 'max:150'],
            'sort' => ['nullable', 'array', 'max:3'],
            'sort.*.field' => ['required', 'string', 'max:64'],
            'sort.*.order' => ['required', 'integer', 'in:1,-1'],
            'visibleColumns' => ['required', 'array', 'min:1'],
            'visibleColumns.*' => ['string', 'max:64'],
            'columnOrder' => ['nullable', 'array'],
            'columnOrder.*' => ['string', 'max:64'],
            'filters' => ['nullable', 'array'],
            'filters.*' => ['array'],
            'filters.*.op' => [
                'nullable',
                'string',
                Rule::in([
                    // text / enum / badge
                    'contains',
                    'starts_with',
                    'ends_with',
                    'equals',
                    'not_equals',
                    // number
                    'lt',
                    'lte',
                    'gt',
                    'gte',
                    // date
                    'date_equals',
                    'before',
                    'after',
                    'between',
                ]),
            ],
            'filters.*.value' => [
                'required',
                function (string $attribute, mixed $value, \Closure $fail): void {
                    if (is_object($value)) {
                        $fail('Filter values must be scalar (string, int, bool, null) or an array of scalars.');
                        return;
                    }
                    if (is_array($value)) {
                        foreach ($value as $item) {
                            if (is_array($item) || is_object($item)) {
                                $fail('Filter values must be scalar (string, int, bool, null) or an array of scalars.');
                                return;
                            }
                        }
                    }
                },
            ],
            'globalSearch' => ['nullable', 'string', 'max:200'],
        ];
    }

    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator): void {
            $content = $this->getContent();
            if ($content !== false && strlen($content) > self::MAX_PAYLOAD_BYTES) {
                $validator->errors()->add(
                    'body',
                    'The request payload must not exceed ' . (self::MAX_PAYLOAD_BYTES / 1024) . ' KB.'
                );
            }
        });
    }
}
