<?php

declare(strict_types=1);

namespace App\Framework\Admin\FormFields\Fields;

use App\Framework\Admin\FormFields\Components\FieldWrapper;
use App\Framework\Admin\FormFields\FormField;
use App\Framework\Admin\FormFields\ValueObjects\FieldAttributes;
use App\Framework\Admin\FormFields\ValueObjects\FieldMetadata;
use App\Framework\Admin\FormFields\ValueObjects\FieldOptions;
use App\Framework\View\FormBuilder;
use App\Framework\View\ValueObjects\FormElement;

/**
 * Select Dropdown Field
 *
 * Select field with options using composition
 */
final readonly class SelectField implements FormField
{
    public function __construct(
        private FieldMetadata $metadata,
        private FieldAttributes $attributes,
        private FieldWrapper $wrapper,
        private FieldOptions $options,
        private mixed $value = null
    ) {
    }

    public static function create(
        string $name,
        string $label,
        array $options,
        mixed $value = null,
        bool $required = false,
        ?string $help = null,
        ?string $placeholder = null
    ): self {
        return new self(
            metadata: new FieldMetadata($name, $label, $help),
            attributes: new FieldAttributes(
                name: $name,
                id: $name,
                required: $required
            ),
            wrapper: new FieldWrapper(),
            options: new FieldOptions($options, $placeholder),
            value: $value
        );
    }

    public function render(FormBuilder $form): FormBuilder
    {
        $attrArray = $this->attributes->toArray();

        $optionsHtml = $this->options->toHtml((string) $this->value);

        $select = FormElement::create('select', $attrArray, $optionsHtml);
        $wrapped = $this->wrapper->wrap($select, $this->metadata);

        return $form->addElement($wrapped);
    }

    public function getName(): string
    {
        return $this->metadata->name;
    }

    public function getValue(): mixed
    {
        return $this->value;
    }

    public function getLabel(): string
    {
        return $this->metadata->label;
    }
}
