<?php

declare(strict_types=1);

namespace App\Framework\FormGenerator;

use App\Framework\Validation\Rules\Email;
use App\Framework\Validation\Rules\Pattern;
use App\Framework\Validation\Rules\Required;
use App\Framework\Validation\Rules\StringLength;
use App\Framework\Validation\Rules\Url;

/**
 * Maps Validation Attributes to HTML5 form attributes
 */
final readonly class ValidationAttributeMapper
{
    /**
     * Map validation attributes to HTML attributes
     *
     * @param array<object> $validationAttributes
     * @return array<string, mixed>
     */
    public function map(array $validationAttributes): array
    {
        $htmlAttributes = [];

        foreach ($validationAttributes as $attribute) {
            $mapped = $this->mapSingleAttribute($attribute);
            $htmlAttributes = array_merge($htmlAttributes, $mapped);
        }

        return $htmlAttributes;
    }

    /**
     * Map single validation attribute to HTML attributes
     *
     * @return array<string, mixed>
     */
    private function mapSingleAttribute(object $attribute): array
    {
        return match (true) {
            $attribute instanceof Required => ['required' => true],

            $attribute instanceof StringLength => $this->mapStringLength($attribute),

            $attribute instanceof Pattern => [
                'pattern' => $attribute->pattern,
            ],

            $attribute instanceof Email => [
                'type' => 'email',
            ],

            $attribute instanceof Url => [
                'type' => 'url',
            ],

            default => []
        };
    }

    /**
     * Map StringLength to minlength/maxlength
     *
     * @return array<string, int>
     */
    private function mapStringLength(StringLength $rule): array
    {
        $attributes = [];

        if ($rule->min !== null) {
            $attributes['minlength'] = $rule->min;
        }

        if ($rule->max !== null) {
            $attributes['maxlength'] = $rule->max;
        }

        return $attributes;
    }
}
