<?php
declare(strict_types=1);

namespace Celena\Plugin\Leads\Support;

/**
 * Рендер формы конструктора в разметку cz-form лендинга. Сохраняет honeypot,
 * data-* атрибуты (для landing.js) и мультиязычные подписи через lang_key.
 * Submit обрабатывает общий обработчик landing.js по [data-cz-form].
 */
final class FormRenderer
{
    /** Полный HTML формы. */
    public static function render(array $form): string
    {
        $fields   = is_array($form['fields'] ?? null) ? $form['fields'] : [];
        $settings = is_array($form['settings'] ?? null) ? $form['settings'] : [];
        $slug     = (string) ($form['slug'] ?? '');
        $isDefault = !empty($settings['is_default']);

        $id        = $isDefault ? 'czForm' : 'czForm-' . preg_replace('/[^a-z0-9\-]/', '', $slug);
        $endpoint  = (string) ($settings['endpoint'] ?? ('/api/forms/' . $slug . '/submit'));
        $event     = (string) ($settings['track_event'] ?? '');
        $conv      = (string) ($settings['conversion_send_to'] ?? '');
        $value     = (string) ($settings['lead_value'] ?? '0');
        $currency  = (string) ($settings['lead_currency'] ?? 'EUR');

        $title    = self::txt($settings, 'title', 'title_lang');
        $submit   = self::txt($settings, 'submit_text', 'submit_lang') ?: 'Send';
        $sending  = self::txt($settings, 'sending_text', 'sending_lang') ?: 'Sending…';
        $okTitle  = self::txt($settings, 'ok_title', 'ok_title_lang') ?: 'Thank you!';
        $okText   = self::txt($settings, 'ok_text', 'ok_text_lang');
        $okWa     = self::txt($settings, 'ok_wa', 'ok_wa_lang');
        $note     = self::txt($settings, 'note', 'note_lang');

        $attrs = 'class="cz-form" id="' . e($id) . '" data-cz-form'
            . ' data-endpoint="' . e($endpoint) . '"'
            . ($event !== '' ? ' data-event="' . e($event) . '"' : '')
            . ($conv !== ''  ? ' data-conversion="' . e($conv) . '"' : '')
            . ' data-value="' . e($value) . '" data-currency="' . e($currency) . '"'
            . ' data-sending="' . e($sending) . '"'
            . ' data-ok-title="' . e($okTitle) . '"'
            . ' data-ok-text="' . e($okText) . '"'
            . ' data-ok-wa="' . e($okWa) . '"';

        $html = '<form ' . $attrs . '>';
        if ($title !== '') {
            $html .= '<h3>' . e($title) . '</h3>';
        }
        $html .= self::fieldsHtml($fields);
        // Honeypot — антиспам (как в текущей форме)
        $html .= '<input type="text" name="website_url" class="cz-hp" tabindex="-1" autocomplete="off" aria-hidden="true">';
        $html .= '<button class="cz-btn cz-btn--primary" type="submit" id="' . ($isDefault ? 'czSubmit' : e($id) . '-submit') . '">'
            . e($submit) . ' <svg class="cz-ic"><use href="#i-arrow"/></svg></button>';
        if ($note !== '') {
            $html .= '<p class="cz-fnote"><svg class="cz-ic"><use href="#i-lock"/></svg> ' . e($note) . '</p>';
        }
        $html .= '</form>';
        return $html;
    }

    /** Поля: half-поля группируются по 2 в cz-frow, full — отдельной строкой. */
    private static function fieldsHtml(array $fields): string
    {
        $out = '';
        $pendingHalf = [];
        $flush = function () use (&$pendingHalf, &$out) {
            if ($pendingHalf === []) return;
            $out .= '<div class="cz-frow">' . implode('', $pendingHalf) . '</div>';
            $pendingHalf = [];
        };
        foreach ($fields as $f) {
            if (!is_array($f) || ($f['type'] ?? '') === 'hidden') {
                if (is_array($f) && ($f['type'] ?? '') === 'hidden') {
                    $out .= self::input($f);
                }
                continue;
            }
            $cell = self::cell($f);
            if (($f['width'] ?? 'full') === 'half') {
                $pendingHalf[] = $cell;
                if (count($pendingHalf) === 2) $flush();
            } else {
                $flush();
                $out .= $cell;
            }
        }
        $flush();
        return $out;
    }

    /** Одно поле в обёртке cz-field. */
    private static function cell(array $f): string
    {
        $type = (string) ($f['type'] ?? 'text');
        $label = self::label($f);
        $help = (string) ($f['help'] ?? '');
        if ($type === 'checkbox' || $type === 'consent') {
            $req = !empty($f['required']) ? ' required' : '';
            return '<span class="cz-field cz-field--check"><label class="cz-check">'
                . '<input type="checkbox" name="' . e((string) $f['key']) . '" value="1"' . $req . '> '
                . e($label) . '</label>'
                . ($help !== '' ? '<small class="cz-help">' . e($help) . '</small>' : '')
                . '</span>';
        }
        return '<span class="cz-field"><label>' . e($label) . '</label>' . self::input($f)
            . ($help !== '' ? '<small class="cz-help">' . e($help) . '</small>' : '')
            . '</span>';
    }

    private static function input(array $f): string
    {
        $type = (string) ($f['type'] ?? 'text');
        $key  = e((string) ($f['key'] ?? ''));
        $ph   = isset($f['placeholder']) ? ' placeholder="' . e((string) $f['placeholder']) . '"' : '';
        $req  = !empty($f['required']) ? ' required' : '';
        $aria = ' aria-label="' . e(self::label($f)) . '"';

        switch ($type) {
            case 'textarea':
                return '<textarea name="' . $key . '"' . $ph . $req . $aria . '></textarea>';
            case 'select':
                $opts = '';
                foreach (self::options($f) as $o) {
                    $opts .= '<option value="' . e($o['value']) . '">' . e($o['label']) . '</option>';
                }
                return '<select name="' . $key . '"' . $req . $aria . '>' . $opts . '</select>';
            case 'radio':
                $r = '<span class="cz-radios">';
                foreach (self::options($f) as $o) {
                    $r .= '<label class="cz-radio"><input type="radio" name="' . $key . '" value="' . e($o['value']) . '"' . $req . '> ' . e($o['label']) . '</label>';
                }
                return $r . '</span>';
            case 'checkboxes':
                $r = '<span class="cz-radios">';
                foreach (self::options($f) as $o) {
                    $r .= '<label class="cz-radio"><input type="checkbox" name="' . $key . '[]" value="' . e($o['value']) . '"> ' . e($o['label']) . '</label>';
                }
                return $r . '</span>';
            case 'hidden':
                return '<input type="hidden" name="' . $key . '" value="' . e((string) ($f['default'] ?? '')) . '">';
            case 'tel':
                // Международный формат: + и цифры (допускаются пробелы/скобки/дефисы).
                $tph = isset($f['placeholder']) ? $ph : ' placeholder="+1 555 123 4567"';
                return '<input type="tel" name="' . $key . '"' . $tph . $req . $aria
                    . ' inputmode="tel" maxlength="20" pattern="\\+[0-9 ()\\-]{7,19}"'
                    . ' title="Международный формат: + код страны, затем номер">';
            case 'number':
            case 'date':
            case 'email':
            case 'text':
            default:
                $t = in_array($type, ['number', 'date', 'email'], true) ? $type : 'text';
                return '<input type="' . $t . '" name="' . $key . '"' . $ph . $req . $aria . '>';
        }
    }

    /** @return array<int, array{value:string,label:string}> */
    private static function options(array $f): array
    {
        $out = [];
        foreach ((array) ($f['options'] ?? []) as $o) {
            if (is_array($o)) {
                $val = (string) ($o['value'] ?? '');
                $lab = !empty($o['lang']) ? __((string) $o['lang']) : (string) ($o['label'] ?? $val);
            } else {
                $val = (string) $o;
                $lab = (string) $o;
            }
            if ($val !== '') {
                $out[] = ['value' => $val, 'label' => $lab];
            }
        }
        return $out;
    }

    private static function label(array $f): string
    {
        return !empty($f['lang_key']) ? __((string) $f['lang_key']) : (string) ($f['label'] ?? '');
    }

    /** Текст из настроек: lang-ключ имеет приоритет над литералом. */
    private static function txt(array $settings, string $literalKey, string $langKey): string
    {
        if (!empty($settings[$langKey])) {
            return __((string) $settings[$langKey]);
        }
        return (string) ($settings[$literalKey] ?? '');
    }
}
