<?php

/**
 * Хелпер для работы с формами из массивов конфигурации
 *
 * @package Flowaxy\Support\Helpers
 */

declare(strict_types=1);

namespace Flowaxy\Support\Helpers;

final class FormHelper
{
    /**
     * Рендеринг формы из массива конфигурации
     *
     * @param array<string, mixed> $config Конфигурация формы
     * @return string HTML формы
     */
    public static function render(array $config): string
    {
        $action = $config['action'] ?? '';
        $method = $config['method'] ?? 'POST';
        $fields = $config['fields'] ?? [];
        $submitButton = $config['submit'] ?? ['text' => 'Отправить', 'type' => 'primary'];
        $attributes = $config['attributes'] ?? [];

        $attributesString = '';
        foreach ($attributes as $key => $value) {
            $attributesString .= ' ' . htmlspecialchars($key) . '="' . htmlspecialchars((string)$value) . '"';
        }

        $html = '<form action="' . htmlspecialchars($action) . '" method="' . htmlspecialchars($method) . '"' . $attributesString . '>';

        foreach ($fields as $field) {
            $html .= self::renderField($field);
        }

        $html .= '<div class="form-actions">';
        $html .= ButtonHelper::render($submitButton);
        $html .= '</div>';

        $html .= '</form>';

        return $html;
    }

    /**
     * Рендеринг поля формы
     *
     * @param array<string, mixed> $field Конфигурация поля
     * @return string HTML поля
     */
    public static function renderField(array $field): string
    {
        $type = $field['type'] ?? 'text';
        $name = $field['name'] ?? '';
        $label = $field['label'] ?? '';
        $value = $field['value'] ?? '';
        $placeholder = $field['placeholder'] ?? '';
        $required = $field['required'] ?? false;
        $attributes = $field['attributes'] ?? [];
        $options = $field['options'] ?? [];

        $html = '<div class="mb-3">';

        if (!empty($label)) {
            $html .= '<label for="' . htmlspecialchars($name) . '" class="form-label">';
            $html .= htmlspecialchars($label);
            if ($required) {
                $html .= ' <span class="text-danger">*</span>';
            }
            $html .= '</label>';
        }

        $attributesString = '';
        if ($required) {
            $attributesString .= ' required';
        }
        foreach ($attributes as $key => $val) {
            $attributesString .= ' ' . htmlspecialchars($key) . '="' . htmlspecialchars((string)$val) . '"';
        }

        switch ($type) {
            case 'textarea':
                $html .= '<textarea name="' . htmlspecialchars($name) . '" id="' . htmlspecialchars($name) . '" class="form-control" placeholder="' . htmlspecialchars($placeholder) . '"' . $attributesString . '>' . htmlspecialchars($value) . '</textarea>';
                break;

            case 'select':
                $html .= '<select name="' . htmlspecialchars($name) . '" id="' . htmlspecialchars($name) . '" class="form-select"' . $attributesString . '>';
                foreach ($options as $optValue => $optLabel) {
                    $selected = ($optValue == $value) ? ' selected' : '';
                    $html .= '<option value="' . htmlspecialchars((string)$optValue) . '"' . $selected . '>' . htmlspecialchars($optLabel) . '</option>';
                }
                $html .= '</select>';
                break;

            case 'checkbox':
            case 'radio':
                foreach ($options as $optValue => $optLabel) {
                    $checked = ($optValue == $value) ? ' checked' : '';
                    $html .= '<div class="form-check">';
                    $html .= '<input type="' . htmlspecialchars($type) . '" name="' . htmlspecialchars($name) . '" id="' . htmlspecialchars($name . '_' . $optValue) . '" value="' . htmlspecialchars((string)$optValue) . '" class="form-check-input"' . $checked . $attributesString . '>';
                    $html .= '<label class="form-check-label" for="' . htmlspecialchars($name . '_' . $optValue) . '">' . htmlspecialchars($optLabel) . '</label>';
                    $html .= '</div>';
                }
                break;

            default:
                $html .= '<input type="' . htmlspecialchars($type) . '" name="' . htmlspecialchars($name) . '" id="' . htmlspecialchars($name) . '" class="form-control" value="' . htmlspecialchars($value) . '" placeholder="' . htmlspecialchars($placeholder) . '"' . $attributesString . '>';
        }

        $html .= '</div>';

        return $html;
    }

    /**
     * Валидация формы по правилам из массива
     *
     * @param array<string, mixed> $data Данные формы
     * @param array<string, array<string, mixed>> $rules Правила валидации
     * @return array<string, string> Ошибки валидации (пустой массив если валидация прошла)
     */
    public static function validate(array $data, array $rules): array
    {
        $errors = [];

        foreach ($rules as $field => $fieldRules) {
            $value = $data[$field] ?? null;

            foreach ($fieldRules as $rule => $ruleValue) {
                switch ($rule) {
                    case 'required':
                        if ($ruleValue && empty($value)) {
                            $errors[$field] = 'Поле обязательно для заполнения';
                        }
                        break;

                    case 'min':
                        if (strlen((string)$value) < $ruleValue) {
                            $errors[$field] = 'Минимальная длина: ' . $ruleValue . ' символов';
                        }
                        break;

                    case 'max':
                        if (strlen((string)$value) > $ruleValue) {
                            $errors[$field] = 'Максимальная длина: ' . $ruleValue . ' символов';
                        }
                        break;

                    case 'email':
                        if ($ruleValue && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                            $errors[$field] = 'Неверный формат email';
                        }
                        break;
                }
            }
        }

        return $errors;
    }
}
