<?php

declare(strict_types=1);

namespace App\Framework\View;

use App\Framework\Http\Session\FormIdGenerator;
use App\Framework\View\ValueObjects\FormElement;
use App\Framework\View\ValueObjects\FormId;
use App\Framework\View\ValueObjects\HtmlElement;

final readonly class FormBuilder
{
    /**
     * @var HtmlElement[]
     */
    private array $elements;

    public function __construct(
        private FormElement $form,
        private FormIdGenerator $formIdGenerator,
        array $elements = []
    ) {
        $this->elements = $elements;
    }

    public static function create(
        string $action = '',
        string $method = 'post',
        ?FormIdGenerator $formIdGenerator = null
    ): self {
        $generator = $formIdGenerator ?? new FormIdGenerator();
        $form = FormElement::form($action, $method);

        return new self($form, $generator);
    }

    public function withHtmlId(string $htmlId): self
    {
        $newForm = new FormElement(
            $this->form->tag,
            $this->form->attributes->withId($htmlId),
            $this->form->content
        );

        return new self($newForm, $this->formIdGenerator, $this->elements);
    }

    public function withAction(string $action): self
    {
        $newForm = new FormElement(
            $this->form->tag,
            $this->form->attributes->withAction($action),
            $this->form->content
        );

        return new self($newForm, $this->formIdGenerator, $this->elements);
    }

    public function withMethod(string $method): self
    {
        $newForm = new FormElement(
            $this->form->tag,
            $this->form->attributes->withMethod($method),
            $this->form->content
        );

        return new self($newForm, $this->formIdGenerator, $this->elements);
    }

    public function withClass(string $class): self
    {
        $newForm = $this->form->withClass($class);

        return new self($newForm, $this->formIdGenerator, $this->elements);
    }

    public function addElement(HtmlElement $element): self
    {
        return new self($this->form, $this->formIdGenerator, [...$this->elements, $element]);
    }

    public function addTextInput(string $name, string $value = '', string $label = ''): self
    {
        $elements = [];

        if ($label) {
            $elements[] = FormElement::label($label, $name);
        }

        $elements[] = FormElement::textInput($name, $value)->withId($name);

        return new self($this->form, $this->formIdGenerator, [...$this->elements, ...$elements]);
    }

    public function addEmailInput(string $name, string $value = '', string $label = ''): self
    {
        $elements = [];

        if ($label) {
            $elements[] = FormElement::label($label, $name);
        }

        $elements[] = FormElement::emailInput($name, $value)
            ->withId($name)
            ->withRequired();

        return new self($this->form, $this->formIdGenerator, [...$this->elements, ...$elements]);
    }

    public function addPasswordInput(string $name, string $label = ''): self
    {
        $elements = [];

        if ($label) {
            $elements[] = FormElement::label($label, $name);
        }

        $elements[] = FormElement::passwordInput($name)
            ->withId($name)
            ->withRequired();

        return new self($this->form, $this->formIdGenerator, [...$this->elements, ...$elements]);
    }

    public function addFileInput(string $name, string $label = '', bool $required = false): self
    {
        $elements = [];

        if ($label) {
            $elements[] = FormElement::label($label, $name);
        }

        $input = FormElement::fileInput($name)->withId($name);
        if ($required) {
            $input = $input->withRequired();
        }

        $elements[] = $input;

        return new self($this->form, $this->formIdGenerator, [...$this->elements, ...$elements]);
    }

    public function addTextarea(string $name, string $content = '', string $label = ''): self
    {
        $elements = [];

        if ($label) {
            $elements[] = FormElement::label($label, $name);
        }

        $elements[] = FormElement::textarea($name, $content)->withId($name);

        return new self($this->form, $this->formIdGenerator, [...$this->elements, ...$elements]);
    }

    public function addSubmitButton(string $text = 'Submit'): self
    {
        return $this->addElement(FormElement::submitButton($text));
    }

    public function addHiddenInput(string $name, string $value): self
    {
        return $this->addElement(FormElement::hiddenInput($name, $value));
    }

    // CSRF Token und FormId werden automatisch vom FormProcessor hinzugefügt
    // Diese Methoden sind nicht mehr nötig, da sie durch das Template Processing automatisch eingefügt werden

    public function build(): string
    {
        $formContent = '';

        foreach ($this->elements as $element) {
            $formContent .= (string) $element . "\n";
        }

        $formWithContent = new FormElement(
            $this->form->tag,
            $this->form->attributes,
            $formContent
        );

        return (string) $formWithContent;
    }

    public function __toString(): string
    {
        return $this->build();
    }
}
