<?php

namespace App\Http\Requests;

use App\Enums\MappingOperator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;

class UpdateExportMapTemplate extends ExportMapTemplateRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    #[\Override]
    public function rules(): array
    {
        return [
            'is_published' => ['required', 'boolean'],
            'sales_channel' => ['nullable', 'string', 'max:100'],
            'title' => ['required', 'string', 'max:255'],
            'type' => ['sometimes', 'string', Rule::in(array_keys(config('export_maps.types', [])))],
            'columns' => ['required', 'array', 'min:1'],
            'columns.*' => ['required', 'string'],
            'headers' => ['nullable', 'array'],
            'headers.*' => ['nullable', 'string'],
            'mapping_rules' => ['nullable', 'array'],
            'mapping_rules.*.when' => ['required', 'array'],
            'mapping_rules.*.when.field' => ['required', 'string'],
            'mapping_rules.*.when.op' => ['required', 'string', Rule::in(MappingOperator::values())],
            'mapping_rules.*.when.value' => ['nullable'],
            'mapping_rules.*.then' => ['required', 'array', 'min:1'],
            'mapping_rules.*.then.*.action' => ['required', 'string', Rule::in(['set', 'append', 'prepend'])],
            'mapping_rules.*.then.*.target' => ['required', 'string'],
            'mapping_rules.*.then.*.value' => ['nullable'],
        ];
    }

    public function withValidator(Validator $validator): void
    {
        $validator->after(function ($validator) {
            foreach (($this->input('mapping_rules', []) ?? []) as $i => $rule) {
                $op = MappingOperator::fromString($rule['when']['op'] ?? null);
                if (!$op) {
                    continue;
                }

                $val = $rule['when']['value'] ?? null;

                // value presence
                if ($op->expectsValue() && ($val === null || (is_string($val) && trim($val) === ''))) {
                    $validator->errors()
                        ->add("mapping_rules.$i.when.value", 'This operator requires a value.');
                }

                // numeric for GT/GTE/LT/LTE
                if ($op->isNumeric() && !is_numeric($val)) {
                    $validator->errors()
                        ->add("mapping_rules.$i.when.value", 'Value must be numeric for this operator.');
                }
            }
        });
    }

    #[\Override]
    public function messages(): array
    {
        return [
            'columns.required' => 'At least one column is required.',
            'columns.*.distinct' => 'Columns must be unique.',
            'mapping_rules.*.when.field.required' => 'Each rule must specify a "when.field".',
            'mapping_rules.*.when.op.in' => 'Unsupported operator.',
            'mapping_rules.*.then.min' => 'Each rule must have at least one THEN action.',
            'mapping_rules.*.then.*.action.in' => 'Only "set", "append", and "prepend" actions are supported.',
            'mapping_rules.*.then.*.target.required' => 'Each THEN action must specify a target field.',
        ];
    }
}
