/**
 * Schema Builder - Visual Mode
 * 
 * Handles visual form rendering and interactions
 * 
 * @package CustomSchemaSchemafy
 * @since 2.0.0
 */

(function ($) {
    'use strict';

    window.SchemafyBuilder = window.SchemafyBuilder || {};

    /**
     * Visual Mode Handler
     */
    SchemafyBuilder.Visual = {

        /**
         * Container element
         */
        $container: null,

        /**
         * Initialize visual mode
         */
        init: function () {
            this.$container = $('#schemafy-visual-form');
            this.bindImageUploader();
            this.bindRepeaters();
        },

        /**
         * Render form from field configuration
         */
        render: function (fieldConfig, fieldValues) {
            if (!this.$container) {
                this.init();
            }

            this.$container.empty();

            if (!fieldConfig || !fieldConfig.fields) {
                this.$container.append(this.renderExtraFields(fieldValues));
                this.bindImageUploader();
                this.bindRepeaters();
                this.bindExtraFieldsToggle();
                return;
            }

            // Render each field
            fieldConfig.fields.forEach(function (field) {
                const value = fieldValues[field.name] !== undefined ? fieldValues[field.name] : '';
                const fieldHTML = this.renderField(field, value);
                this.$container.append(fieldHTML);
            }.bind(this));

            // Append extra fields section at the bottom
            this.$container.append(this.renderExtraFields(fieldValues));

            // Re-bind events after rendering
            this.bindImageUploader();
            this.bindRepeaters();
            this.bindExtraFieldsToggle();
        },

        /**
         * Render single field
         */
        renderField: function (field, value) {
            const $group = $('<div>').addClass('schemafy-field-group').attr('data-field-name', field.name);

            // Label
            const $label = $('<label>').addClass('schemafy-field-label').text(field.label);
            if (field.required) {
                $label.append(' <span class="schemafy-required">*</span>');
            }
            $group.append($label);

            // Help text
            if (field.helpText) {
                $group.append(
                    $('<div>').addClass('schemafy-field-help').text(field.helpText)
                );
            }

            // Field input
            const $input = this.createInputElement(field, value);
            $group.append($input);

            // Character counter
            if (field.maxLength) {
                const currentLength = String(value).length;
                const $counter = $('<div>').addClass('schemafy-char-counter');
                $counter.html(
                    '<span class="current">' + currentLength + '</span> / ' +
                    '<span class="max">' + field.maxLength + '</span>'
                );
                $group.append($counter);

                // Update counter on input
                $input.on('input', function () {
                    $counter.find('.current').text($(this).val().length);
                });
            }

            // Validation container
            $group.append($('<div>').addClass('schemafy-field-validation'));

            return $group;
        },

        /**
         * Create input element based on field type
         */
        createInputElement: function (field, value) {
            switch (field.type) {
                case 'text':
                    return this.createTextInput(field, value);

                case 'textarea':
                    return this.createTextarea(field, value);

                case 'select':
                    return this.createSelect(field, value);

                case 'number':
                    return this.createNumberInput(field, value);

                case 'url':
                    return this.createUrlInput(field, value);

                case 'datetime':
                    return this.createDatetimeInput(field, value);

                case 'image':
                    return this.createImageUploader(field, value);

                case 'group':
                    return this.createGroup(field, value);

                case 'repeater':
                case 'array':
                    return this.createRepeater(field, value);

                case 'date':
                    return this.createDateInput(field, value);

                default:
                    return this.createTextInput(field, value);
            }
        },

        /**
         * Create text input
         */
        createTextInput: function (field, value) {
            const $input = $('<input>')
                .attr('type', 'text')
                .attr('name', field.name)
                .addClass('schemafy-field-input')
                .val(value);

            if (field.placeholder) $input.attr('placeholder', field.placeholder);
            if (field.maxLength) $input.attr('maxlength', field.maxLength);
            if (field.required) $input.prop('required', true);

            return $input;
        },

        /**
         * Create textarea
         */
        createTextarea: function (field, value) {
            const $textarea = $('<textarea>')
                .attr('name', field.name)
                .addClass('schemafy-field-textarea')
                .val(value)
                .attr('rows', field.rows || 4);

            if (field.placeholder) $textarea.attr('placeholder', field.placeholder);
            if (field.maxLength) $textarea.attr('maxlength', field.maxLength);
            if (field.required) $textarea.prop('required', true);

            return $textarea;
        },

        /**
         * Create select dropdown
         */
        createSelect: function (field, value) {
            const $select = $('<select>')
                .attr('name', field.name)
                .addClass('schemafy-field-select');

            $select.append($('<option>').val('').text('-- Select --'));

            if (field.options && Array.isArray(field.options)) {
                field.options.forEach(function (option) {
                    const $option = $('<option>').val(option).text(option);
                    if (option === value) {
                        $option.prop('selected', true);
                    }
                    $select.append($option);
                });
            }

            if (field.required) $select.prop('required', true);

            return $select;
        },

        /**
         * Create number input
         */
        createNumberInput: function (field, value) {
            const $input = $('<input>')
                .attr('type', 'number')
                .attr('name', field.name)
                .addClass('schemafy-field-input schemafy-field-number')
                .val(value);

            if (field.min !== undefined) $input.attr('min', field.min);
            if (field.max !== undefined) $input.attr('max', field.max);
            if (field.step) $input.attr('step', field.step);
            if (field.required) $input.prop('required', true);

            return $input;
        },

        /**
         * Create URL input
         */
        createUrlInput: function (field, value) {
            const $input = $('<input>')
                .attr('type', 'url')
                .attr('name', field.name)
                .addClass('schemafy-field-input schemafy-field-url')
                .val(value);

            if (field.placeholder) $input.attr('placeholder', field.placeholder);
            if (field.required) $input.prop('required', true);

            return $input;
        },

        /**
         * Create datetime input
         */
        createDatetimeInput: function (field, value) {
            const $input = $('<input>')
                .attr('type', 'datetime-local')
                .attr('name', field.name)
                .addClass('schemafy-field-input schemafy-field-datetime')
                .val(value);

            if (field.required) $input.prop('required', true);

            return $input;
        },

        /**
         * Create date input
         */
        createDateInput: function (field, value) {
            const $input = $('<input>')
                .attr('type', 'date')
                .attr('name', field.name)
                .addClass('schemafy-field-input schemafy-field-date')
                .val(value);

            if (field.required) $input.prop('required', true);

            return $input;
        },

        /**
         * Create image uploader
         */
        createImageUploader: function (field, value) {
            const $container = $('<div>').addClass('schemafy-image-field');
            const $hidden = $('<input>')
                .attr('type', 'hidden')
                .attr('name', field.name)
                .addClass('schemafy-image-value')
                .val(value);

            $container.append($hidden);

            if (value) {
                const $preview = $('<div>').addClass('schemafy-image-preview');
                $preview.append($('<img>').attr('src', value));
                $preview.append(
                    $('<button>')
                        .attr('type', 'button')
                        .addClass('schemafy-remove-image')
                        .text('✕')
                );
                $container.append($preview);
            }

            const i18nVis = (typeof schemafyBuilder !== 'undefined' && schemafyBuilder.i18n) ? schemafyBuilder.i18n : ((typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n) ? schemafy_ajax.i18n : {});
            const $btn = $('<button>')
                .attr('type', 'button')
                .addClass('schemafy-btn schemafy-btn-secondary schemafy-upload-image')
                .text(i18nVis.upload_image || 'Upload Image');

            $container.append($btn);

            return $container;
        },

        /**
         * Create group of fields.
         * Sub-field input names are prefixed with the parent field name so
         * onFieldChange captures "address.streetAddress" instead of bare "streetAddress",
         * enabling correct dot-notation reconstruction in fieldValuesToJSON().
         */
        createGroup: function (field, value) {
            const parentName = field.name; // e.g., 'address', 'aggregateRating'
            const $container = $('<div>').addClass('schemafy-field-group-container');

            if (field.fields && Array.isArray(field.fields)) {
                field.fields.forEach(function (subField) {
                    const subValue = (value && typeof value === 'object' && value[subField.name] !== undefined)
                        ? value[subField.name]
                        : '';
                    // Prefix the input name so the DOM always uses dot-notation paths
                    const prefixedField = Object.assign({}, subField, {
                        name: parentName + '.' + subField.name
                    });
                    const $subField = this.renderField(prefixedField, subValue);
                    $container.append($subField);
                }.bind(this));
            }

            return $container;
        },

        /**
         * Create repeater field
         */
        createRepeater: function (field, value) {
            const $container = $('<div>')
                .addClass('schemafy-repeater-field')
                .attr('data-field-name', field.name);

            const $items = $('<div>').addClass('schemafy-repeater-items');

            // Render existing items
            if (Array.isArray(value) && value.length > 0) {
                value.forEach(function (itemValue, index) {
                    const $item = this.createRepeaterItem(field, itemValue, index);
                    $items.append($item);
                }.bind(this));
            }

            $container.append($items);

            // Add button
            const i18nRep = (typeof schemafyBuilder !== 'undefined' && schemafyBuilder.i18n) ? schemafyBuilder.i18n : ((typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n) ? schemafy_ajax.i18n : {});
            const $addBtn = $('<button>')
                .attr('type', 'button')
                .addClass('schemafy-btn schemafy-btn-secondary schemafy-repeater-add')
                .text(i18nRep.add_item || '+ Add Item');

            $container.append($addBtn);

            return $container;
        },

        /**
         * Create single repeater item
         */
        createRepeaterItem: function (field, value, index) {
            const $item = $('<div>')
                .addClass('schemafy-repeater-item')
                .attr('data-index', index);

            if (field.fields && Array.isArray(field.fields)) {
                field.fields.forEach(function (subField) {
                    const subValue = (value && value[subField.name]) || '';
                    const $subField = this.renderField(subField, subValue);
                    $item.append($subField);
                }.bind(this));
            }

            const i18nRemove = (typeof schemafyBuilder !== 'undefined' && schemafyBuilder.i18n) ? schemafyBuilder.i18n : ((typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n) ? schemafy_ajax.i18n : {});
            const $removeBtn = $('<button>')
                .attr('type', 'button')
                .addClass('schemafy-btn schemafy-btn-danger schemafy-repeater-remove')
                .text(i18nRemove.remove_item || 'Remove');

            $item.append($removeBtn);

            return $item;
        },

        /**
         * Render the "Additional Fields" panel.
         * Shows unknown fields (not in fieldConfig) from the original schema
         * so users can view and edit them as raw JSON. They are auto-merged on save.
         */
        renderExtraFields: function (fieldValues) {
            const $section = $('<div>').addClass('schemafy-extra-fields-section');

            // Determine which keys are covered by the current field config
            const knownKeys = new Set();
            if (SchemafyBuilder.App.fieldConfig && SchemafyBuilder.App.fieldConfig.fields) {
                SchemafyBuilder.App.fieldConfig.fields.forEach(function (f) {
                    knownKeys.add(f.name);
                    if (f.fields) {
                        f.fields.forEach(function (sf) { knownKeys.add(f.name + '.' + sf.name); });
                    }
                });
            }

            // Collect unknown fields from _originalData
            const original = SchemafyBuilder.App._originalData || {};
            const unknown = {};
            Object.entries(original).forEach(function ([key, val]) {
                // Always expose @id — important for entity linking
                if (key === '@id') { unknown[key] = val; return; }
                // Skip @type (handled separately) and fields already in the form
                if (key.startsWith('@') || knownKeys.has(key)) return;
                unknown[key] = val;
            });

            const hasUnknown = Object.keys(unknown).length > 0;
            const label = hasUnknown
                ? 'Additional Fields (' + Object.keys(unknown).length + ' preserved)'
                : 'Additional Fields (JSON)';
            const note = hasUnknown
                ? 'These fields from your schema are not in the form above. They are automatically preserved on save — edit here to update them.'
                : 'Add any Schema.org properties not covered by the form above. Enter valid JSON object (without @context / @type).';

            $section.append(
                $('<div>').addClass('schemafy-extra-fields-toggle').append(
                    $('<button>').attr('type', 'button')
                        .addClass('schemafy-extra-fields-btn')
                        .html(
                            '<span class="schemafy-extra-icon">' + (hasUnknown ? '📋' : '＋') + '</span> ' +
                            label +
                            ' <span class="schemafy-extra-arrow">▾</span>'
                        )
                )
            );

            const $content = $('<div>').addClass('schemafy-extra-fields-content').hide();
            $content.append($('<p>').addClass('schemafy-field-help').text(note));

            const $textarea = $('<textarea>')
                .attr('id', 'schemafy-extra-fields-json')
                .addClass('schemafy-extra-fields-textarea')
                .attr('rows', hasUnknown ? Math.min(20, Object.keys(unknown).length * 2 + 5) : 6)
                .attr('placeholder', '{\n  "@id": "https://yoursite.com/#entity",\n  "sameAs": ["https://www.linkedin.com/company/..."],\n  "amenityFeature": [...]\n}')
                .val(hasUnknown ? JSON.stringify(unknown, null, 2) : '');

            $content.append($textarea);
            $section.append($content);

            return $section;
        },

        /**
         * Bind the extra fields accordion toggle
         */
        bindExtraFieldsToggle: function () {
            $(document).off('click', '.schemafy-extra-fields-btn');
            $(document).on('click', '.schemafy-extra-fields-btn', function (e) {
                e.preventDefault();
                const $content = $(this).closest('.schemafy-extra-fields-section').find('.schemafy-extra-fields-content');
                const $arrow = $(this).find('.schemafy-extra-arrow');
                $content.slideToggle(180, function () {
                    $arrow.text($content.is(':visible') ? '▴' : '▾');
                });
            });
        },

        /**
         * Bind WordPress media uploader
         */
        bindImageUploader: function () {
            $(document).off('click', '.schemafy-upload-image');
            $(document).on('click', '.schemafy-upload-image', function (e) {
                e.preventDefault();
                e.stopPropagation();

                // Check if WordPress media is available
                if (typeof wp === 'undefined' || typeof wp.media === 'undefined') {
                    console.error('WordPress Media Library not loaded. Please refresh the page.');
                    alert('Media Library not available. Please refresh the page and try again.');
                    return;
                }

                const $btn = $(this);
                const $container = $btn.closest('.schemafy-image-field');
                const $input = $container.find('.schemafy-image-value');

                // Disable button to prevent double-clicks
                $btn.prop('disabled', true);

                // WordPress media uploader
                const i18nMedia = (typeof schemafyBuilder !== 'undefined' && schemafyBuilder.i18n) ? schemafyBuilder.i18n : ((typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n) ? schemafy_ajax.i18n : {});
                const frame = wp.media({
                    title: i18nMedia.select_image_title || 'Select Image',
                    button: { text: i18nMedia.use_this_image || 'Use this image' },
                    multiple: false,
                    library: { type: 'image' }
                });

                frame.on('select', function () {
                    const attachment = frame.state().get('selection').first().toJSON();
                    $input.val(attachment.url).trigger('change');

                    // Update preview
                    $container.find('.schemafy-image-preview').remove();
                    const $preview = $('<div>').addClass('schemafy-image-preview');
                    $preview.append($('<img>').attr('src', attachment.url));
                    $preview.append(
                        $('<button>')
                            .attr('type', 'button')
                            .addClass('schemafy-remove-image')
                            .text('✕')
                    );
                    $btn.before($preview);
                });

                frame.on('close', function() {
                    // Re-enable button when modal closes
                    $btn.prop('disabled', false);
                });

                frame.open();
            });

            // Remove image
            $(document).off('click', '.schemafy-remove-image');
            $(document).on('click', '.schemafy-remove-image', function (e) {
                e.preventDefault();
                const $container = $(this).closest('.schemafy-image-field');
                $container.find('.schemafy-image-value').val('').trigger('change');
                $(this).closest('.schemafy-image-preview').remove();
            });
        },

        /**
         * Bind repeater add/remove
         */
        bindRepeaters: function () {
            // Add item
            $(document).off('click', '.schemafy-repeater-add');
            $(document).on('click', '.schemafy-repeater-add', function (e) {
                e.preventDefault();

                const $container = $(this).closest('.schemafy-repeater-field');
                const $items = $container.find('.schemafy-repeater-items');
                const newIndex = $items.children().length;

                // Get field config from global
                const fieldName = $container.data('field-name');
                const fieldConfig = SchemafyBuilder.App.getFieldConfigByName(fieldName);

                if (fieldConfig) {
                    const $newItem = SchemafyBuilder.Visual.createRepeaterItem(fieldConfig, {}, newIndex);
                    $items.append($newItem);
                }
            });

            // Remove item
            $(document).off('click', '.schemafy-repeater-remove');
            $(document).on('click', '.schemafy-repeater-remove', function (e) {
                e.preventDefault();
                $(this).closest('.schemafy-repeater-item').remove();
            });
        }
    };

    // Initialize on document ready
    $(document).ready(function () {
        if (typeof schemafyBuilder !== 'undefined') {
            SchemafyBuilder.Visual.init();
        }
    });

})(jQuery);
