<?php

namespace GriffinForms\Admin\Html\FormControls\Field\FieldSettings;

class ImageselectionSettings extends \GriffinForms\Admin\Html\FormControls\Field\FieldSettings\Format
{
    private const DEFAULTS = [
        'options' => [],
        'columns_desktop' => 3,
        'columns_mobile' => 2,
        'show_title' => true,
        'show_description' => true,
        'aspect_ratio' => '1:1',
        'randomise' => false,
        'default_selected' => [],
    ];

    private const ASPECT_OPTIONS = [
        '1:1' => '1:1',
        '4:3' => '4:3',
        '16:9' => '16:9',
        '3:2' => '3:2',
        'free' => 'Free',
    ];

    public function html()
    {
        wp_enqueue_media();
        wp_enqueue_script('thickbox');
        wp_enqueue_style('thickbox');

        $s = is_array($this->value) ? $this->value : [];
        $s = array_merge(self::DEFAULTS, $s);

        $options = $this->normalizeOptions($s['options']);
        $columns_desktop = max(1, min(6, absint($s['columns_desktop'])));
        $columns_mobile = max(1, min(3, absint($s['columns_mobile'])));
        $show_title = !empty($s['show_title']);
        $show_description = !empty($s['show_description']);
        $aspect_ratio = in_array($s['aspect_ratio'], array_keys(self::ASPECT_OPTIONS), true) ? $s['aspect_ratio'] : '1:1';
        $randomise = !empty($s['randomise']);
        $default_selected = array_values(array_filter(array_map('sanitize_key', is_array($s['default_selected']) ? $s['default_selected'] : [])));
        $default_selected_map = array_fill_keys($default_selected, true);
        ?>
        <div class="imageselection-settings" id="gf-imageselection-settings-wrap">
            <div class="mb-4">
                <label class="form-label fw-semibold mb-2"><?php echo esc_html($this->lang->getText('imageselection_options', 'label')); ?></label>
                <div id="gf-imageselection-options-wrap" style="max-height:720px;overflow-y:auto;overflow-x:hidden;padding-right:4px;margin-bottom:12px;">
                    <?php foreach ($options as $index => $option) : ?>
                        <?php echo $this->renderOptionRow($index, $option); ?>
                    <?php endforeach; ?>
                </div>

                <button type="button" class="button button-secondary mt-2" id="gf-imageselection-add-option">
                    <?php esc_html_e('Add Option', 'griffinforms-form-builder'); ?>
                </button>

                <script type="text/template" id="gf-imageselection-option-template">
                    <?php
                    $template = [
                        'image_id' => 0,
                        'image_url' => '',
                        'title' => '',
                        'description' => '',
                        'value' => '__value__',
                        'is_none_option' => false,
                    ];
                    echo $this->renderOptionRow('__INDEX__', $template);
                    ?>
                </script>
                <div class="form-text text-muted mt-2"><?php echo esc_html($this->lang->getText('imageselection_options', 'description')); ?></div>
            </div>

            <div class="row g-3 mb-4">
                <div class="col-md-6">
                    <label class="form-label" for="gf-imageselection-columns-desktop"><?php echo esc_html($this->lang->getText('imageselection_columns_desktop', 'label')); ?></label>
                    <select class="form-select form-select-sm griffinforms-field griffinforms-formcontrol" id="gf-imageselection-columns-desktop">
                        <?php for ($i = 1; $i <= 6; $i++) : ?>
                            <option value="<?php echo esc_attr($i); ?>" <?php selected($columns_desktop, $i); ?>><?php echo esc_html($i); ?></option>
                        <?php endfor; ?>
                    </select>
                    <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_columns_desktop', 'description')); ?></div>
                </div>

                <div class="col-md-6">
                    <label class="form-label" for="gf-imageselection-columns-mobile"><?php echo esc_html($this->lang->getText('imageselection_columns_mobile', 'label')); ?></label>
                    <select class="form-select form-select-sm griffinforms-field griffinforms-formcontrol" id="gf-imageselection-columns-mobile">
                        <?php for ($i = 1; $i <= 3; $i++) : ?>
                            <option value="<?php echo esc_attr($i); ?>" <?php selected($columns_mobile, $i); ?>><?php echo esc_html($i); ?></option>
                        <?php endfor; ?>
                    </select>
                    <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_columns_mobile', 'description')); ?></div>
                </div>

                <div class="col-md-6">
                    <label class="form-label" for="gf-imageselection-aspect-ratio"><?php echo esc_html($this->lang->getText('imageselection_aspect_ratio', 'label')); ?></label>
                    <select class="form-select form-select-sm griffinforms-field griffinforms-formcontrol" id="gf-imageselection-aspect-ratio">
                        <?php foreach (self::ASPECT_OPTIONS as $key => $label) : ?>
                            <option value="<?php echo esc_attr($key); ?>" <?php selected($aspect_ratio, $key); ?>><?php echo esc_html($label); ?></option>
                        <?php endforeach; ?>
                    </select>
                    <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_aspect_ratio', 'description')); ?></div>
                </div>

                <div class="col-md-6">
                    <div class="d-flex flex-column gap-2 pt-md-4">
                        <label class="d-flex align-items-center gap-2 mb-0">
                            <input type="checkbox" class="griffinforms-field griffinforms-formcontrol" id="gf-imageselection-show-title" value="1" <?php checked($show_title); ?>>
                            <span><?php echo esc_html($this->lang->getText('imageselection_show_title', 'label')); ?></span>
                        </label>
                        <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_show_title', 'description')); ?></div>

                        <label class="d-flex align-items-center gap-2 mb-0 mt-2">
                            <input type="checkbox" class="griffinforms-field griffinforms-formcontrol" id="gf-imageselection-show-description" value="1" <?php checked($show_description); ?>>
                            <span><?php echo esc_html($this->lang->getText('imageselection_show_description', 'label')); ?></span>
                        </label>
                        <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_show_description', 'description')); ?></div>

                        <label class="d-flex align-items-center gap-2 mb-0 mt-2">
                            <input type="checkbox" class="griffinforms-field griffinforms-formcontrol" id="gf-imageselection-randomise" value="1" <?php checked($randomise); ?>>
                            <span><?php echo esc_html($this->lang->getText('imageselection_randomise', 'label')); ?></span>
                        </label>
                        <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_randomise', 'description')); ?></div>
                    </div>
                </div>
            </div>

            <div class="mb-3">
                <label class="form-label fw-semibold mb-2"><?php echo esc_html($this->lang->getText('imageselection_default_selected', 'label')); ?></label>
                <div id="gf-imageselection-default-selected-list" class="border rounded p-3 bg-white">
                    <?php if (!empty($options)) : ?>
                        <?php foreach ($options as $option) : ?>
                            <?php
                            $value = sanitize_key($option['value']);
                            $label = trim((string) $option['title']) !== '' ? (string) $option['title'] : $value;
                            ?>
                            <label class="d-flex align-items-center gap-2 mb-2">
                                <input type="checkbox"
                                    class="gf-imageselection-default-selected-item"
                                    value="<?php echo esc_attr($value); ?>"
                                    <?php checked(isset($default_selected_map[$value])); ?>>
                                <span><?php echo esc_html($label); ?></span>
                            </label>
                        <?php endforeach; ?>
                    <?php else : ?>
                        <span class="text-muted small"><?php esc_html_e('Add options first to choose defaults.', 'griffinforms-form-builder'); ?></span>
                    <?php endif; ?>
                </div>
                <div class="form-text text-muted mt-2"><?php echo esc_html($this->lang->getText('imageselection_default_selected', 'description')); ?></div>
            </div>
        </div>

        <script>
        (function($) {
            var wrap = document.getElementById('gf-imageselection-settings-wrap');
            if (!wrap) return;

            var optionsWrap = document.getElementById('gf-imageselection-options-wrap');
            var template = document.getElementById('gf-imageselection-option-template');
            var defaultList = document.getElementById('gf-imageselection-default-selected-list');
            var mediaFrame = null;

            function generateSlug() {
                if (window.crypto && window.crypto.getRandomValues) {
                    var bytes = new Uint8Array(4);
                    window.crypto.getRandomValues(bytes);
                    return 'opt_' + Array.from(bytes).map(function(byte) {
                        return byte.toString(16).padStart(2, '0');
                    }).join('');
                }

                return 'opt_' + Math.random().toString(16).slice(2, 10).padEnd(8, '0').slice(0, 8);
            }

            function nextIndex() {
                var rows = optionsWrap.querySelectorAll('.gf-imageselection-option-row');
                var max = -1;
                rows.forEach(function(row) {
                    var idx = parseInt(row.getAttribute('data-index'), 10);
                    if (!isNaN(idx) && idx > max) {
                        max = idx;
                    }
                });
                return max + 1;
            }

            function ensureRowValue(row) {
                var input = row.querySelector('.gf-imageselection-option-value');
                if (input && (!input.value || /^__value__$/i.test(input.value))) {
                    input.value = generateSlug();
                }
                var code = row.querySelector('.gf-imageselection-option-value-code');
                if (input && code) {
                    code.textContent = input.value || '';
                }
            }

            function updateMoveButtons() {
                var rows = optionsWrap.querySelectorAll('.gf-imageselection-option-row');
                rows.forEach(function(row, index) {
                    var up = row.querySelector('.gf-imageselection-move-up');
                    var down = row.querySelector('.gf-imageselection-move-down');
                    if (up) up.disabled = index === 0;
                    if (down) down.disabled = index === rows.length - 1;
                });
            }

            function enforceSingleNoneOption(activeRow) {
                if (!activeRow) return;

                var activeCheckbox = activeRow.querySelector('.gf-imageselection-option-is-none');
                if (!activeCheckbox || !activeCheckbox.checked) return;

                optionsWrap.querySelectorAll('.gf-imageselection-option-row').forEach(function(row) {
                    if (row === activeRow) return;

                    var checkbox = row.querySelector('.gf-imageselection-option-is-none');
                    if (checkbox) {
                        checkbox.checked = false;
                    }
                });
            }

            function refreshDefaultSelected() {
                if (!defaultList) return;

                var selected = {};
                defaultList.querySelectorAll('.gf-imageselection-default-selected-item:checked').forEach(function(input) {
                    selected[input.value] = true;
                });

                defaultList.innerHTML = '';

                var rows = optionsWrap.querySelectorAll('.gf-imageselection-option-row');
                if (!rows.length) {
                    defaultList.innerHTML = '<span class="text-muted small"><?php echo esc_js(__('Add options first to choose defaults.', 'griffinforms-form-builder')); ?></span>';
                    return;
                }

                rows.forEach(function(row) {
                    ensureRowValue(row);
                    var value = row.querySelector('.gf-imageselection-option-value').value || '';
                    if (!value) return;

                    var title = row.querySelector('.gf-imageselection-option-title').value.trim();
                    var label = title || value;

                    var wrapLabel = document.createElement('label');
                    wrapLabel.className = 'd-flex align-items-center gap-2 mb-2';

                    var checkbox = document.createElement('input');
                    checkbox.type = 'checkbox';
                    checkbox.className = 'gf-imageselection-default-selected-item';
                    checkbox.value = value;
                    checkbox.checked = !!selected[value];

                    var span = document.createElement('span');
                    span.textContent = label;

                    wrapLabel.appendChild(checkbox);
                    wrapLabel.appendChild(span);
                    defaultList.appendChild(wrapLabel);
                });
            }

            function updateThumb(row, url) {
                var img = row.querySelector('.gf-imageselection-option-thumb');
                var placeholder = row.querySelector('.gf-imageselection-option-thumb-placeholder');

                if (!img || !placeholder) return;

                if (url) {
                    img.src = url;
                    img.classList.remove('d-none');
                    placeholder.classList.add('d-none');
                } else {
                    img.removeAttribute('src');
                    img.classList.add('d-none');
                    placeholder.classList.remove('d-none');
                }
            }

            function bindRow(row) {
                ensureRowValue(row);
                enforceSingleNoneOption(row);
                updateThumb(row, row.querySelector('.gf-imageselection-option-image-url').value || '');

                row.addEventListener('input', function(e) {
                    if (e.target.classList.contains('gf-imageselection-option-title')) {
                        refreshDefaultSelected();
                    }
                });

                row.addEventListener('click', function(e) {
                    var chooseBtn = e.target.closest('.gf-imageselection-choose-image');
                    var clearBtn = e.target.closest('.gf-imageselection-clear-image');
                    var removeBtn = e.target.closest('.gf-imageselection-remove-option');
                    var upBtn = e.target.closest('.gf-imageselection-move-up');
                    var downBtn = e.target.closest('.gf-imageselection-move-down');

                    if (chooseBtn) {
                        e.preventDefault();
                        if (typeof wp === 'undefined' || !wp.media) return;

                        mediaFrame = wp.media({
                            title: '<?php echo esc_js(__('Choose image', 'griffinforms-form-builder')); ?>',
                            button: { text: '<?php echo esc_js(__('Use this image', 'griffinforms-form-builder')); ?>' },
                            multiple: false
                        });

                        mediaFrame.off('select');
                        mediaFrame.on('select', function() {
                            var attachment = mediaFrame.state().get('selection').first().toJSON();
                            var imageId = row.querySelector('.gf-imageselection-option-image-id');
                            var imageUrl = row.querySelector('.gf-imageselection-option-image-url');
                            var url = attachment.sizes && attachment.sizes.medium ? attachment.sizes.medium.url : (attachment.url || '');
                            imageId.value = attachment.id || 0;
                            imageUrl.value = url;
                            updateThumb(row, url);
                        });

                        mediaFrame.open();
                        return;
                    }

                    if (clearBtn) {
                        e.preventDefault();
                        row.querySelector('.gf-imageselection-option-image-id').value = 0;
                        row.querySelector('.gf-imageselection-option-image-url').value = '';
                        updateThumb(row, '');
                        return;
                    }

                    if (removeBtn) {
                        e.preventDefault();
                        row.remove();
                        updateMoveButtons();
                        refreshDefaultSelected();
                        return;
                    }

                    if (upBtn && row.previousElementSibling) {
                        e.preventDefault();
                        optionsWrap.insertBefore(row, row.previousElementSibling);
                        updateMoveButtons();
                        refreshDefaultSelected();
                        return;
                    }

                    if (downBtn && row.nextElementSibling) {
                        e.preventDefault();
                        optionsWrap.insertBefore(row.nextElementSibling, row);
                        updateMoveButtons();
                        refreshDefaultSelected();
                    }
                });

                row.addEventListener('change', function(e) {
                    if (e.target.classList.contains('gf-imageselection-option-is-none')) {
                        enforceSingleNoneOption(row);
                    }
                });
            }

            function addRow() {
                if (!template) return;

                var index = nextIndex();
                var slug = generateSlug();
                var html = template.innerHTML
                    .split('__INDEX__').join(index)
                    .split('__VALUE__').join(slug)
                    .split('__value__').join(slug);

                var tmp = document.createElement('div');
                tmp.innerHTML = html.trim();
                var row = tmp.firstElementChild;
                if (!row) return;

                optionsWrap.appendChild(row);
                bindRow(row);
                updateMoveButtons();
                refreshDefaultSelected();
            }

            optionsWrap.querySelectorAll('.gf-imageselection-option-row').forEach(function(row) {
                bindRow(row);
            });

            var addBtn = document.getElementById('gf-imageselection-add-option');
            if (addBtn) {
                addBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    addRow();
                });
            }

            updateMoveButtons();
            refreshDefaultSelected();
        })(jQuery);
        </script>
        <?php
    }

    private function normalizeOptions($raw): array
    {
        $raw = is_array($raw) ? $raw : [];
        $options = [];

        foreach ($raw as $option) {
            if (!is_array($option)) {
                continue;
            }

            $value = sanitize_key((string) ($option['value'] ?? ''));
            if ($value === '') {
                $value = $this->uid('opt');
            }

            $options[] = [
                'image_id' => absint($option['image_id'] ?? 0),
                'image_url' => esc_url((string) ($option['image_url'] ?? '')),
                'title' => sanitize_text_field((string) ($option['title'] ?? '')),
                'description' => sanitize_text_field((string) ($option['description'] ?? '')),
                'value' => $value,
                'is_none_option' => !empty($option['is_none_option']),
            ];
        }

        return $options;
    }

    private function renderOptionRow($index, array $option): string
    {
        $image_id = absint($option['image_id'] ?? 0);
        $image_url = esc_url((string) ($option['image_url'] ?? ''));
        $title = (string) ($option['title'] ?? '');
        $description = (string) ($option['description'] ?? '');
        $value = sanitize_key((string) ($option['value'] ?? ''));
        $is_none_option = !empty($option['is_none_option']);

        ob_start();
        ?>
        <div class="gf-imageselection-option-row card mb-3" data-index="<?php echo esc_attr($index); ?>">
            <div class="card-body">
                <div class="d-flex justify-content-between align-items-start gap-3 flex-wrap">
                    <div class="d-flex gap-3 flex-wrap align-items-start">
                        <div class="border rounded d-flex align-items-center justify-content-center bg-light position-relative" style="width:120px;height:80px;overflow:hidden;">
                            <img class="gf-imageselection-option-thumb <?php echo $image_url ? '' : 'd-none'; ?>" src="<?php echo esc_url($image_url); ?>" alt="" style="width:100%;height:100%;object-fit:cover;">
                            <span class="gf-imageselection-option-thumb-placeholder text-muted small <?php echo $image_url ? 'd-none' : ''; ?>"><?php esc_html_e('No image', 'griffinforms-form-builder'); ?></span>
                        </div>

                        <div class="d-flex flex-column gap-2">
                            <div class="d-flex gap-2 flex-wrap">
                                <button type="button" class="button button-secondary gf-imageselection-choose-image"><?php esc_html_e('Choose Image', 'griffinforms-form-builder'); ?></button>
                                <button type="button" class="button gf-imageselection-clear-image"><?php esc_html_e('Clear', 'griffinforms-form-builder'); ?></button>
                            </div>
                            <small class="text-muted">
                                <?php echo esc_html($this->lang->getText('imageselection_option_value', 'label')); ?>:
                                <code class="gf-imageselection-option-value-code"><?php echo esc_html($value); ?></code>
                            </small>
                        </div>
                    </div>

                    <div class="d-flex gap-2">
                        <button type="button" class="button gf-imageselection-move-up"><?php esc_html_e('Up', 'griffinforms-form-builder'); ?></button>
                        <button type="button" class="button gf-imageselection-move-down"><?php esc_html_e('Down', 'griffinforms-form-builder'); ?></button>
                        <button type="button" class="button button-link-delete gf-imageselection-remove-option"><?php esc_html_e('Remove', 'griffinforms-form-builder'); ?></button>
                    </div>
                </div>

                <input type="hidden" class="gf-imageselection-option-image-id griffinforms-field griffinforms-formcontrol" value="<?php echo esc_attr($image_id); ?>">
                <input type="hidden" class="gf-imageselection-option-image-url griffinforms-field griffinforms-formcontrol" value="<?php echo esc_attr($image_url); ?>">
                <input type="hidden" class="gf-imageselection-option-value griffinforms-field griffinforms-formcontrol" value="<?php echo esc_attr($value); ?>">

                <div class="row g-3 mt-1">
                    <div class="col-md-12">
                        <label class="form-label"><?php echo esc_html($this->lang->getText('imageselection_option_title', 'label')); ?></label>
                        <input type="text" class="form-control gf-imageselection-option-title griffinforms-field griffinforms-formcontrol" value="<?php echo esc_attr($title); ?>">
                        <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_option_title', 'description')); ?></div>
                    </div>
                    <div class="col-md-12">
                        <label class="form-label"><?php echo esc_html($this->lang->getText('imageselection_option_description', 'label')); ?></label>
                        <textarea rows="2" class="w-100 gf-imageselection-option-description griffinforms-field griffinforms-formcontrol"><?php echo esc_textarea($description); ?></textarea>
                        <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_option_description', 'description')); ?></div>
                    </div>
                    <div class="col-12">
                        <label class="d-flex align-items-center gap-2 mb-0">
                            <input type="checkbox" class="gf-imageselection-option-is-none griffinforms-field griffinforms-formcontrol" value="1" <?php checked($is_none_option); ?>>
                            <span><?php echo esc_html($this->lang->getText('imageselection_none_option', 'label')); ?></span>
                        </label>
                        <div class="form-text text-muted"><?php echo esc_html($this->lang->getText('imageselection_none_option', 'description')); ?></div>
                    </div>
                </div>
            </div>
        </div>
        <?php

        return trim((string) ob_get_clean());
    }

    private function uid(string $prefix): string
    {
        return $prefix . '_' . bin2hex(random_bytes(4));
    }
}
