<?php

declare(strict_types=1);

namespace App\Framework\View\Processors;

use App\Framework\DI\Container;
use App\Framework\Http\Session\FormDataStorage;
use App\Framework\Http\Session\FormIdGenerator;
use App\Framework\Http\Session\SessionInterface;
use App\Framework\Http\Session\ValidationErrorBag;
use App\Framework\Template\Processing\StringProcessor;
use App\Framework\View\RenderContext;

readonly class CsrfReplaceProcessor implements StringProcessor
{
    public function __construct(
        private Container $container,
        private FormIdGenerator $formIdGenerator,
    ) {
    }

    public function process(string $html, RenderContext $context): string
    {
        return $html;
        // Check if we have any form-related placeholders
        $hasToken = str_contains($html, '___TOKEN___');
        $hasOldInput = str_contains($html, '___OLD_INPUT_');
        $hasError = str_contains($html, '___ERROR_');

        if (! $hasToken && ! $hasOldInput && ! $hasError) {
            return $html;
        }

        /* OLD CODE - DEACTIVATED
        error_log("CsrfReplaceProcessor: process() called");

        // Check if we have any form-related placeholders
        $hasToken = str_contains($html, '___TOKEN___');
        $hasOldInput = str_contains($html, '___OLD_INPUT_');
        $hasError = str_contains($html, '___ERROR_');

        error_log("CsrfReplaceProcessor: Placeholders - Token: " . ($hasToken ? 'YES' : 'NO') .
                  ", OldInput: " . ($hasOldInput ? 'YES' : 'NO') .
                  ", Error: " . ($hasError ? 'YES' : 'NO'));

        if (!$hasToken && !$hasOldInput && !$hasError) {
            error_log("CsrfReplaceProcessor: No placeholders found, skipping");
            return $html;
        }
        */

        // Get session from container (available after SessionMiddleware)
        if (! $this->container->has(SessionInterface::class)) {
            return $html;
        }

        $session = $this->container->get(SessionInterface::class);
        $formIds = $this->formIdGenerator->extractFormIdsFromHtml($html);

        if (empty($formIds)) {
            return $html;
        }

        // Process each form
        foreach ($formIds as $formId) {
            // 1. Replace CSRF tokens
            if (str_contains($html, '___TOKEN___')) {
                $token = $session->csrf->generateToken($formId);
                $html = $this->replaceTokenForFormId($html, $formId, $token->toString());
            }

            // 2. Replace old input values
            $html = $this->replaceOldInputForForm($html, $formId, $session);

            // 3. Replace error messages
            $html = $this->replaceErrorsForForm($html, $formId, $session);
        }

        return $html;
    }

    private function replaceTokenForFormId(string $html, string $formId, string $token): string
    {
        // Suche nach dem Token-Platzhalter, der zur entsprechenden Form-ID gehört
        // Wir müssen den Kontext der Form berücksichtigen
        $pattern = '/(<form[^>]*>.*?<input[^>]*name=["\']_form_id["\'][^>]*value=["\']' . preg_quote($formId, '/') . '["\'][^>]*>.*?)<input[^>]*name=["\']_token["\'][^>]*value=["\']___TOKEN___["\'][^>]*>/s';

        return preg_replace_callback($pattern, function ($matches) use ($token) {
            return str_replace('___TOKEN___', $token, $matches[0]);
        }, $html);
    }

    private function replaceOldInputForForm(string $html, string $formId, SessionInterface $session): string
    {
        $formDataStorage = new FormDataStorage($session);

        if (! $formDataStorage->has($formId)) {
            // No old data, remove placeholders
            return $this->cleanupOldInputPlaceholders($html);
        }

        $oldData = $formDataStorage->get($formId);

        foreach ($oldData as $fieldName => $value) {
            // Text inputs and textareas
            $placeholder = "___OLD_INPUT_{$fieldName}___";
            if (str_contains($html, $placeholder)) {
                $escapedValue = htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
                $html = str_replace($placeholder, $escapedValue, $html);
            }

            // Select options
            if (is_scalar($value)) {
                $selectPattern = "___OLD_SELECT_{$fieldName}_{$value}___";
                $html = str_replace(
                    "data-selected-if=\"{$selectPattern}\"",
                    'selected="selected"',
                    $html
                );
            }

            // Radio buttons
            if (is_scalar($value)) {
                $radioPattern = "___OLD_RADIO_{$fieldName}_{$value}___";
                $html = str_replace(
                    "data-checked-if=\"{$radioPattern}\"",
                    'checked="checked"',
                    $html
                );
            }

            // Checkboxes
            if (is_array($value)) {
                foreach ($value as $checkboxValue) {
                    $checkboxPattern = "___OLD_CHECKBOX_{$fieldName}_{$checkboxValue}___";
                    $html = str_replace(
                        "data-checked-if=\"{$checkboxPattern}\"",
                        'checked="checked"',
                        $html
                    );
                }
            } elseif ($value) {
                $checkboxValue = is_bool($value) ? '1' : (string) $value;
                $checkboxPattern = "___OLD_CHECKBOX_{$fieldName}_{$checkboxValue}___";
                $html = str_replace(
                    "data-checked-if=\"{$checkboxPattern}\"",
                    'checked="checked"',
                    $html
                );
            }
        }

        return $this->cleanupOldInputPlaceholders($html);
    }

    private function replaceErrorsForForm(string $html, string $formId, SessionInterface $session): string
    {
        $errorBag = new ValidationErrorBag($session);

        if (! $errorBag->has($formId)) {
            // No errors, remove error placeholders
            return $this->cleanupErrorPlaceholders($html);
        }

        $errors = $errorBag->get($formId);

        foreach ($errors as $fieldName => $fieldErrors) {
            $placeholder = "___ERROR_{$fieldName}___";

            if (! str_contains($html, $placeholder)) {
                continue;
            }

            if (empty($fieldErrors)) {
                // Remove error display
                $html = $this->removeErrorDisplay($html, $fieldName);

                continue;
            }

            // Build error HTML
            $errorHtml = '';
            foreach ($fieldErrors as $error) {
                $escapedError = htmlspecialchars($error, ENT_QUOTES, 'UTF-8');
                $errorHtml .= "<span class=\"error-message\">{$escapedError}</span>";
            }

            // Replace placeholder with actual errors
            $html = str_replace($placeholder, $errorHtml, $html);

            // Add error class to the field
            $html = $this->addErrorClassToField($html, $fieldName);
        }

        return $this->cleanupErrorPlaceholders($html);
    }

    private function cleanupOldInputPlaceholders(string $html): string
    {
        // Remove remaining old input placeholders
        $html = preg_replace('/___OLD_INPUT_[^_]+___/', '', $html);

        // Remove remaining data attributes
        $html = preg_replace('/\s*data-selected-if="[^"]*"/', '', $html);
        $html = preg_replace('/\s*data-checked-if="[^"]*"/', '', $html);

        return $html;
    }

    private function cleanupErrorPlaceholders(string $html): string
    {
        // Remove empty error displays
        $html = preg_replace('/<div[^>]*class="[^"]*error-display[^"]*"[^>]*>___ERROR_[^_]+___<\/div>/', '', $html);
        $html = preg_replace('/___ERROR_[^_]+___/', '', $html);

        return $html;
    }

    private function removeErrorDisplay(string $html, string $fieldName): string
    {
        $pattern = '/<div[^>]*class="[^"]*error-display[^"]*"[^>]*data-field="' . preg_quote($fieldName, '/') . '"[^>]*>.*?<\/div>/s';

        return preg_replace($pattern, '', $html);
    }

    private function addErrorClassToField(string $html, string $fieldName): string
    {
        // Add 'error' class to field - handle existing class attribute
        $pattern = '/(<(?:input|select|textarea)[^>]*name="' . preg_quote($fieldName, '/') . '"[^>]*class="[^"]*)(")([^>]*>)/';
        $html = preg_replace($pattern, '$1 error$2$3', $html);

        // Handle fields without existing class attribute
        $pattern = '/(<(?:input|select|textarea)[^>]*name="' . preg_quote($fieldName, '/') . '"[^>]*?)(?:\s|>)/';
        $html = preg_replace($pattern, '$1 class="error" ', $html);

        return $html;
    }
}
