<?php

declare(strict_types=1);

namespace App\Framework\View\Processors;

use App\Framework\Http\Session\FormIdGenerator;
use App\Framework\Template\Processing\DomProcessor;
use App\Framework\View\DomFormService;
use App\Framework\View\DomWrapper;
use App\Framework\View\RenderContext;
use App\Framework\View\ValueObjects\FormId;
use Dom\Element;

final readonly class FormProcessor implements DomProcessor
{
    public function __construct(
        private DomFormService $formService,
        private FormIdGenerator $formIdGenerator,
    ) {
    }

    public function process(DomWrapper $dom, RenderContext $context): DomWrapper
    {
        $forms = $dom->document->querySelectorAll('form');
        #error_log("FormProcessor: Found " . count($forms) . " forms to process");

        // Debug: Track when FormProcessor runs and what it processes
        $html = $dom->document->saveHTML();
        $containsForm = str_contains($html, '<form');
        $formElements = $dom->document->getElementsByTagName('form');

        /*error_log(sprintf(
            "FormProcessor[%s]: template=%s, forms=%d, hasFormTag=%s, length=%d",
            $context->controllerClass ?? 'unknown',
            $context->template,
            $formElements->length,
            $containsForm ? 'YES' : 'NO',
            strlen($html)
        ));

        // Show a snippet if it's likely an error template
        if (!$containsForm && strlen($html) < 1000) {
            error_log("FormProcessor: HTML snippet (no forms): " . substr($html, 0, 200));
        }

        // Show context if we unexpectedly find no forms
        if (!$containsForm && str_contains(strtolower($context->template), 'contact')) {
            error_log("FormProcessor: WARNING - Contact template has no forms! HTML: " . substr($html, 0, 300));
        }*/

        foreach ($forms as $form) {
            $formId = $this->formIdGenerator->generateFromRenderContext($form, $context);

            // 1. Add CSRF token placeholder
            $this->addCsrfTokenPlaceholder($dom, $form);

            // 2. Add form ID
            $this->addFormId($dom, $form, $formId);

            // 3. Add old input placeholders to form fields
            $this->addOldInputPlaceholders($form);

            // 4. Add error display placeholders
            $this->addErrorDisplayPlaceholders($dom, $form);
        }

        return $dom;
    }

    private function addCsrfTokenPlaceholder(DomWrapper $dom, Element $form): void
    {
        // Check if CSRF token already exists
        $existing = $form->querySelector('input[name="_token"]');
        if ($existing) {
            $existing->setAttribute('value', '___TOKEN___');

            return;
        }

        $csrf = $dom->document->createElement('input');
        $csrf->setAttribute('name', '_token');
        $csrf->setAttribute('type', 'hidden');
        $csrf->setAttribute('value', '___TOKEN___');

        $form->insertBefore($csrf, $form->firstChild);
    }

    private function addFormId(DomWrapper $dom, Element $form, FormId $formId): void
    {
        // Check if form ID already exists
        $existing = $form->querySelector('input[name="_form_id"]');
        if ($existing) {
            $existing->setAttribute('value', (string) $formId);

            return;
        }

        $formIdField = $dom->document->createElement('input');
        $formIdField->setAttribute('name', '_form_id');
        $formIdField->setAttribute('type', 'hidden');
        $formIdField->setAttribute('value', (string) $formId);

        $form->insertBefore($formIdField, $form->firstChild);
    }

    private function addOldInputPlaceholders(Element $form): void
    {
        // Text inputs, email, password, etc.
        $textInputs = $form->querySelectorAll('input[type="text"], input[type="email"], input[type="password"], input[type="url"], input[type="tel"], input[type="number"], input[type="search"], input[name]:not([type])');

        foreach ($textInputs as $input) {
            $name = $input->getAttribute('name');

            if ($name && $input->getAttribute('type') !== 'hidden') {
                // Only set placeholder if no value is already set or if value is empty
                $currentValue = $input->getAttribute('value');

                if (! $currentValue || $currentValue === '') {
                    $input->setAttribute('value', "___OLD_INPUT_{$name}___");
                }
            }
        }

        // Textareas
        $textareas = $form->querySelectorAll('textarea[name]');
        foreach ($textareas as $textarea) {
            $name = $textarea->getAttribute('name');
            if ($name) {
                // Only set placeholder if textarea is empty
                $currentContent = trim($textarea->textContent);
                if (! $currentContent || $currentContent === '') {
                    $textarea->textContent = "___OLD_INPUT_{$name}___";
                }
            }
        }

        // Select dropdowns - add placeholder to each option
        $selects = $form->querySelectorAll('select[name]');
        foreach ($selects as $select) {
            $name = $select->getAttribute('name');
            if ($name) {
                $options = $select->querySelectorAll('option');
                foreach ($options as $option) {
                    $value = $option->getAttribute('value');
                    if ($value) {
                        $option->setAttribute('data-selected-if', "___OLD_SELECT_{$name}_{$value}___");
                    }
                }
            }
        }

        // Radio buttons
        $radios = $form->querySelectorAll('input[type="radio"][name]');
        foreach ($radios as $radio) {
            $name = $radio->getAttribute('name');
            $value = $radio->getAttribute('value');
            if ($name && $value) {
                $radio->setAttribute('data-checked-if', "___OLD_RADIO_{$name}_{$value}___");
            }
        }

        // Checkboxes
        $checkboxes = $form->querySelectorAll('input[type="checkbox"][name]');
        foreach ($checkboxes as $checkbox) {
            $name = $checkbox->getAttribute('name');
            $value = $checkbox->getAttribute('value') ?: '1';
            if ($name) {
                $checkbox->setAttribute('data-checked-if', "___OLD_CHECKBOX_{$name}_{$value}___");
            }
        }
    }

    private function addErrorDisplayPlaceholders(DomWrapper $dom, Element $form): void
    {
        // Find all form fields that could have errors
        $fields = $form->querySelectorAll('input[name], select[name], textarea[name]');

        foreach ($fields as $field) {
            $name = $field->getAttribute('name');
            if (! $name || $field->getAttribute('type') === 'hidden') {
                continue;
            }

            // Check if error display already exists
            $existingError = $form->querySelector(sprintf('.error-display[data-field="%s"]', $name));
            if ($existingError) {
                continue;
            }

            // Create error display placeholder
            $errorDisplay = $dom->document->createElement('div');
            $errorDisplay->setAttribute('class', 'error-display');
            $errorDisplay->setAttribute('data-field', $name);
            $errorDisplay->textContent = "___ERROR_{$name}___";

            // Insert error display after the field
            $parent = $field->parentNode;
            if ($parent && $field->nextSibling) {
                $parent->insertBefore($errorDisplay, $field->nextSibling);
            } else {
                $parent?->appendChild($errorDisplay);
            }
        }
    }
}
