<?php

namespace apexl\Io\modules\formbuilder\Components;

use apexl\Io\enums\HttpMethod;
use apexl\Io\modules\component\Collections\ComponentCollection;
use apexl\Io\modules\component\Collections\ComponentPropertyCollection;
use apexl\Io\modules\component\Component\Component;
use apexl\Io\modules\component\Factories\ComponentPropertyFactory;
use apexl\Io\modules\component\Interfaces\ComponentInterface;
use apexl\Io\modules\formbuilder\Collections\FieldsetCollection;
use apexl\Io\modules\formbuilder\Interfaces\FormComponent;
use apexl\Io\modules\formbuilder\Traits\HasFormChildren;
use apexl\Io\modules\formbuilder\Traits\HasFormIdProperty;
use apexl\Io\modules\formbuilder\Traits\HasTitleProperty;
use apexl\Io\modules\validation\Collections\ValidationRuleCollectionCollection;
use apexl\Io\modules\validation\Interfaces\HasValidationRulesInterface;
use Arrayy\Type\StringCollection;

readonly class Form extends Component implements HasValidationRulesInterface
{
    use HasFormChildren;
    use HasFormIdProperty;
    use HasTitleProperty;

    protected FieldsetCollection $fieldsets;

    public function __construct(
        ComponentPropertyFactory $propertyFactory,
        ComponentPropertyCollection $props,
        ComponentCollection $components,
        StringCollection $classes,
        ?string $componentId = null
    ) {
        parent::__construct(
            $propertyFactory,
            $props,
            $components,
            $classes,
            $componentId
        );
    }

    public function init(): void
    {
        $this->setHeader(5);
        $this->setFormId($this->id);
    }

    public function setHeader($num): static
    {
        return $this->setProperty('header', $num);
    }

    public function setActionUrl(string $url): static
    {
        return $this->setProperty('action', $url);
    }

    function setMethod(HttpMethod $method): static
    {
        return $this->setProperty('method', $method->name);
    }

    public function setSubmitText(string $text): static
    {
        return $this->setProperty('submitText', $text);
    }

    public function removeSubmitButton(bool $state): static
    {
        return $this->setProperty('removeSubmit', $state);
    }

    public function includeClearButton(bool $includeClearButton = true): static
    {
        return $this->setProperty('includeClearButton', $includeClearButton);
    }

    public function setClearButtonText(string $text): static
    {
        return $this->setProperty('clearButtonText', $text);
    }

    public function addComponent(ComponentInterface $component): static
    {
        if (method_exists($component, 'setFormId')) {
            $component->setFormId($this->id);
        }
        parent::addComponent($component);

        return $this;
    }

    public function setValues(array $values): static
    {
        return $this->setProperty('values', $values);
    }

    public function jsonSerialize(): array
    {
        $this->setProperty('schema', $this->schema());
        $this->components->clear();
        return parent::jsonSerialize();
    }

    private function schema(): array
    {
        return $this->components->map(function (Component $component): array {
            if ($component instanceof FormComponent) {
                return $component->toSchema();
            }

            return [
                '$cmp' => $component->name,
                'props' => $component->props->toArray(),
                'components' => $component->components->toArray(),
            ];
        })->toArray();
    }

    public function getValidationRules(ValidationRuleCollectionCollection $rules): ValidationRuleCollectionCollection
    {
        foreach ($this->components as $component) {
            if ($component instanceof HasValidationRulesInterface) {
                $rules = ValidationRuleCollectionCollection::createFromArray([
                    ...$rules->toArray(),
                    ...$component->getValidationRules($rules)->toArray()
                ]);
            }
        }

        return $rules;
    }
}
