<?php
declare(strict_types=1);

namespace Celena\Module\CustomFields;

/**
 * Собирает HTML-инпут для доп. поля по его описанию и текущему значению.
 * Учитывает настройки из JSON-колонки `options`: placeholder, min, max, step,
 * rows, maxlength, список вариантов select/multiselect, дефолтные значения.
 */
final class FieldRenderer
{
    /**
     * @param array<int, array<string, mixed>> $fields
     * @param array<string, string> $values slug => value
     * @return array<int, array<string, string>>
     */
    public static function prepare(array $fields, array $values): array
    {
        $out = [];
        foreach ($fields as $f) {
            $slug = (string) $f['slug'];
            $value = (string) ($values[$slug] ?? '');
            $opts = self::parseOptions($f);
            if ($value === '' && isset($opts['default'])) {
                $value = (string) $opts['default'];
            }
            $out[] = [
                'slug' => $slug,
                'label' => (string) $f['label'],
                'type' => (string) $f['type'],
                'is_required' => (bool) ($f['is_required'] ?? false) ? '1' : '',
                'html' => self::renderInput($f, $value, $opts),
                'help' => (string) ($opts['help'] ?? ''),
            ];
        }
        return $out;
    }

    /** @return array<string, mixed> */
    private static function parseOptions(array $f): array
    {
        if (empty($f['options'])) return [];
        $decoded = json_decode((string) $f['options'], true);
        return is_array($decoded) ? $decoded : [];
    }

    /** @param array<string, mixed> $opts */
    private static function renderInput(array $f, string $value, array $opts): string
    {
        $name = 'cf[' . htmlspecialchars((string) $f['slug'], ENT_QUOTES) . ']';
        $req = ($f['is_required'] ?? false) ? ' required' : '';
        $ev = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
        $ph = isset($opts['placeholder']) ? ' placeholder="' . htmlspecialchars((string) $opts['placeholder'], ENT_QUOTES) . '"' : '';
        $ml = isset($opts['maxlength']) ? ' maxlength="' . (int) $opts['maxlength'] . '"' : '';
        $options = array_values((array) ($opts['values'] ?? []));

        switch ($f['type']) {
            case 'textarea':
                $rows = (int) ($opts['rows'] ?? 3);
                return '<textarea name="' . $name . '"' . $req . $ph . $ml . ' rows="' . $rows . '">' . $ev . '</textarea>';

            case 'number':
                $extra = '';
                if (isset($opts['min']))  $extra .= ' min="' . htmlspecialchars((string) $opts['min'], ENT_QUOTES) . '"';
                if (isset($opts['max']))  $extra .= ' max="' . htmlspecialchars((string) $opts['max'], ENT_QUOTES) . '"';
                if (isset($opts['step'])) $extra .= ' step="' . htmlspecialchars((string) $opts['step'], ENT_QUOTES) . '"';
                return '<input type="number" name="' . $name . '" value="' . $ev . '"' . $req . $extra . '>';

            case 'date':
                $extra = '';
                if (!empty($opts['min_date'])) $extra .= ' min="' . htmlspecialchars((string) $opts['min_date'], ENT_QUOTES) . '"';
                if (!empty($opts['max_date'])) $extra .= ' max="' . htmlspecialchars((string) $opts['max_date'], ENT_QUOTES) . '"';
                return '<input type="date" name="' . $name . '" value="' . $ev . '"' . $req . $extra . '>';

            case 'url':
                return '<input type="url" name="' . $name . '" value="' . $ev . '"' . $req . $ph . '>';

            case 'email':
                return '<input type="email" name="' . $name . '" value="' . $ev . '"' . $req . $ph . '>';

            case 'image':
                $count = (int) ($opts['image_count'] ?? 1);
                $slug = htmlspecialchars((string) $f['slug'], ENT_QUOTES);
                if ($count <= 1) {
                    // Одно изображение: компактный picker с × на миниатюре.
                    $previewId = 'cf_img_prev_' . $slug;
                    $inputId   = 'cf_img_inp_' . $slug;
                    $thumb = $value !== '' ? '<img src="' . e(\Celena\Core\Support\ImageVariant::url($value, 'thumb')) . '" alt="">' : '';
                    return
                        '<div class="cover-inline">'
                        . '<input type="hidden" name="' . $name . '" id="' . $inputId . '" value="' . $ev . '">'
                        . '<div class="cover-thumb" id="' . $previewId . '">' . $thumb . '</div>'
                        . '<button type="button" class="cover-del" data-cover-clear="#' . $inputId . '" data-cover-preview="#' . $previewId . '" title="Убрать">×</button>'
                        . '<button type="button" class="btn btn-secondary" data-media-picker="#' . $inputId . '" data-media-preview="#' . $previewId . '">Выбрать</button>'
                        . '</div>';
                }
                // Галерея: несколько URL в JSON-массиве, multi-picker.
                $wrapId    = 'cf_gal_' . $slug;
                $inputId   = 'cf_gal_inp_' . $slug;
                $pickerId  = 'cf_gal_pick_' . $slug;
                $val = $value !== '' && $value[0] === '[' ? $value : json_encode([$value]);
                $escVal = htmlspecialchars($val, ENT_QUOTES);
                return
                    '<div class="cf-gallery" id="' . $wrapId . '" data-cf-gallery data-max="' . $count . '">'
                    . '<input type="hidden" name="' . $name . '" id="' . $inputId . '" value=\'' . $escVal . '\'>'
                    . '<input type="hidden" id="' . $pickerId . '">'
                    . '<div class="cf-gallery-grid" data-cf-gallery-grid></div>'
                    . '<button type="button" class="btn btn-secondary" id="add-' . $pickerId . '" data-media-picker="#' . $pickerId . '" data-media-multi="1">'
                    . 'Добавить изображения'
                    . '</button>'
                    . '<small class="help" style="display:block;margin-top:6px">Максимум: ' . (int) $count . '. Клик по фото — удалить.</small>'
                    . '</div>';

            case 'checkbox':
                $checked = $value === '1' ? ' checked' : '';
                return '<label class="checkbox"><input type="hidden" name="' . $name . '" value="0"><input type="checkbox" name="' . $name . '" value="1"' . $checked . '> Да</label>';

            case 'select':
                $html = '<select name="' . $name . '"' . $req . '><option value="">— не выбрано —</option>';
                foreach ($options as $opt) {
                    $o = htmlspecialchars((string) $opt, ENT_QUOTES, 'UTF-8');
                    $sel = $value === (string) $opt ? ' selected' : '';
                    $html .= '<option value="' . $o . '"' . $sel . '>' . $o . '</option>';
                }
                return $html . '</select>';

            case 'multiselect':
                $current = json_decode($value, true);
                if (!is_array($current)) $current = [];
                $html = '<select name="' . $name . '[]" multiple size="5">';
                foreach ($options as $opt) {
                    $o = htmlspecialchars((string) $opt, ENT_QUOTES, 'UTF-8');
                    $sel = in_array((string) $opt, $current, true) ? ' selected' : '';
                    $html .= '<option value="' . $o . '"' . $sel . '>' . $o . '</option>';
                }
                return $html . '</select>';

            case 'text':
            default:
                return '<input type="text" name="' . $name . '" value="' . $ev . '"' . $req . $ph . $ml . '>';
        }
    }
}
