/**
 * Sandbox JavaScript - SlideMind
 *
 * Gestion du sandbox avec sessions persistantes, rendu des prompts et export.
 *
 * @package SlideMind
 * @since 2.0.0
 */

(function($) {
    'use strict';

    // Namespace global
    window.SM = window.SM || {};

    SM.Sandbox = {

        // State
        messages: [],
        sessionId: null,
        currentMode: 'config',
        isInitialized: false,
        sourcePostId: null,
        originalValues: null,

        // DOM cache
        $messagesContainer: null,
        $inputField: null,
        $sendButton: null,
        $debugPanel: null,
        $promptDebug: null,
        $sessionStatus: null,

        /**
         * Initialise le sandbox
         */
        init: function() {
            if (this.isInitialized) return;

            // Cache DOM elements
            this.$messagesContainer = $('#sm-sandbox-messages');
            this.$inputField = $('#sm-sandbox-input');
            this.$sendButton = $('#sm-sandbox-send');
            this.$debugPanel = $('#sm-sandbox-debug');
            this.$promptDebug = $('#sm-sandbox-prompt-debug');
            this.$sessionStatus = $('#sm-session-status');

            // Build expand modal
            this.buildVarExpandModal();

            // Bind events
            this.bindEvents();

            // Initialize session
            this.initSession();

            // Initial state
            this.updateInputState();

            // Auto-load pre-selected config data
            var $config = $('#sm-sandbox-config');
            if ($config.val()) {
                this.loadConfigData($config);
            }

            this.isInitialized = true;
        },

        /**
         * Bind tous les événements
         */
        bindEvents: function() {
            var self = this;

            // Mode toggle
            $(document).on('click', '.sm-sandbox-mode', function() {
                self.setMode($(this).data('mode'));
            });

            // Config selection
            $('#sm-sandbox-config').on('change', function() {
                self.updateInputState();
                self.loadConfigData($(this));
            });

            // Temperature slider
            $('#sm-sandbox-temperature').on('input', function() {
                $('#sm-sandbox-temp-value').text($(this).val());
            });

            // Remove variable row
            $(document).on('click', '.sm-sandbox-var-remove', function() {
                self.removeVariableRow($(this).closest('.sm-sandbox-var-row'));
            });

            // Sync variables from prompt on input
            $('#sm-sandbox-prompt').on('input', function() {
                self.syncVariablesFromPrompt();
            });

            // Add output variable row
            $('#sm-sandbox-add-output-var').on('click', function() {
                self.addOutputVariableRow();
            });

            // Remove output variable row
            $(document).on('click', '.sm-sandbox-output-var-remove', function() {
                $(this).closest('.sm-sandbox-output-var-row').remove();
            });

            // Output var type change
            $(document).on('change', '#sm-sandbox-output-vars-list .sm-sandbox-output-var-type', function() {
                var $row = $(this).closest('.sm-sandbox-output-var-row');
                var $wrap = $(this).closest('.sm-sandbox-output-var-type-wrap');
                var type = $(this).val();
                var $values = $row.find('.sm-sandbox-output-var-values');
                var $desc = $row.find('.sm-sandbox-output-var-desc');

                // Enum values field
                if (type === 'enum') {
                    $values.show();
                } else {
                    $values.hide().val('');
                }

                // Type hint badge
                $wrap.find('.sm-sandbox-output-var-type-hint').remove();
                var hints = {
                    booleen: slidemindAdmin.strings.hintBooleanShort,
                    nombre: slidemindAdmin.strings.hintNumberShort
                };
                if (hints[type]) {
                    $wrap.append('<span class="sm-sandbox-output-var-type-hint">' + hints[type] + '</span>');
                }

                // Placeholder contextuel
                var placeholders = {
                    texte: slidemindAdmin.strings.placeholderDescOptional,
                    nombre: slidemindAdmin.strings.placeholderDescNumber,
                    booleen: slidemindAdmin.strings.placeholderDescCondition,
                    enum: slidemindAdmin.strings.placeholderDescOptional
                };
                $desc.attr('placeholder', placeholders[type] || slidemindAdmin.strings.placeholderDescOptional);
            });

            // Force lowercase on output var name
            $(document).on('input', '#sm-sandbox-output-vars-list .sm-sandbox-output-var-name', function() {
                var val = $(this).val().toLowerCase().replace(/[^a-z0-9_]/g, '');
                $(this).val(val);
            });

            // Expand variable button
            $(document).on('click', '.sm-sandbox-var-expand', function() {
                var $row = $(this).closest('.sm-sandbox-var-row');
                self.openVarExpandModal($row);
            });

            // Expand modal: validate
            $(document).on('click', '#sm-var-expand-ok', function() {
                self.closeVarExpandModal(true);
            });

            // Expand modal: overlay click
            $(document).on('click', '#sm-var-expand-modal', function(e) {
                if ($(e.target).is('#sm-var-expand-modal')) {
                    self.closeVarExpandModal(true);
                }
            });

            // Expand modal: close button
            $(document).on('click', '#sm-var-expand-modal .sm-modal-close', function(e) {
                e.preventDefault();
                self.closeVarExpandModal(false);
            });

            // Expand modal: Escape key
            $(document).on('keydown', function(e) {
                if (e.key === 'Escape' && $('#sm-var-expand-modal').hasClass('active')) {
                    self.closeVarExpandModal(false);
                }
            });

            // Clear data-full-value when user manually edits the input
            $(document).on('input', '.sm-sandbox-var-value', function() {
                $(this).removeAttr('data-full-value');
            });

            // Insert variable button
            $(document).on('click', '.sm-insert-variable-btn', function() {
                var name = prompt(slidemindAdmin.strings.variableNamePrompt);
                if (!name) return;

                name = name.replace(/[^a-zA-Z0-9_]/g, '_').toLowerCase();
                var tag = '{{' + name + '}}';
                var targetId = $(this).data('target');
                var $textarea = $('#' + targetId);
                if (!$textarea.length) return;

                var textarea = $textarea[0];
                var start = textarea.selectionStart;
                var end = textarea.selectionEnd;
                var text = $textarea.val();

                $textarea.val(text.substring(0, start) + tag + text.substring(end));
                textarea.selectionStart = textarea.selectionEnd = start + tag.length;
                $textarea.focus();

                // Sync variable rows if targeting the system prompt
                if (targetId === 'sm-sandbox-prompt') {
                    self.syncVariablesFromPrompt();
                }
            });

            // Toggle comparison button on provider change
            $('#sm-sandbox-provider').on('change', function() {
                var $wrap = $('#sm-comparison-btn-wrap');
                if ($wrap.length) {
                    $wrap.toggle($(this).val() === 'openrouter');
                }
            });

            // Reset
            $('#sm-sandbox-reset').on('click', function() {
                self.clearSession();
            });

            // Export
            $('#sm-sandbox-export').on('click', function() {
                self.exportConfig();
            });

            // Send message
            $('#sm-sandbox-form').on('submit', function(e) {
                e.preventDefault();
                self.sendMessage();
            });

            // Apply changes button
            $('#sm-sandbox-apply-changes').on('click', function() {
                self.applyChanges();
            });

            // Track config field changes
            $('#sm-sandbox-model, #sm-sandbox-prompt, #sm-sandbox-max-tokens, #sm-sandbox-response-example').on('change input', function() {
                self.updateConfigActions();
            });
            $('#sm-sandbox-temperature').on('input', function() {
                self.updateConfigActions();
            });

            // Track output variable changes
            $(document).on('change input', '#sm-sandbox-output-vars-list input, #sm-sandbox-output-vars-list select', function() {
                self.updateConfigActions();
            });

            // Track output variable add/remove (delayed to let DOM update)
            $('#sm-sandbox-add-output-var').on('click', function() {
                setTimeout(function() { self.updateConfigActions(); }, 100);
            });
            $(document).on('click', '.sm-sandbox-output-var-remove', function() {
                setTimeout(function() { self.updateConfigActions(); }, 100);
            });

            // Mini tabs for prompt debug
            $(document).on('click', '.sm-tab-mini', function() {
                var tab = $(this).data('tab');
                $('.sm-tab-mini').removeClass('active');
                $(this).addClass('active');
                $('.sm-tab-content-mini').removeClass('active');
                $('.sm-tab-content-mini[data-tab-content="' + tab + '"]').addClass('active');
            });
        },

        /**
         * Initialise ou restaure la session
         */
        initSession: function() {
            var self = this;

            $.ajax({
                url: slidemindAdmin.ajaxUrl,
                method: 'POST',
                data: {
                    action: 'slidemind_sandbox_get_session',
                    nonce: slidemindAdmin.nonce
                },
                success: function(response) {
                    if (response.success) {
                        self.sessionId = response.data.session_id;
                        self.updateSessionStatus(true);

                        // Restore conversation if exists
                        if (response.data.messages && response.data.messages.length > 0) {
                            self.messages = response.data.messages;
                            self.renderConversation();
                            self.showRestoredNotice();
                        }
                    } else {
                        self.updateSessionStatus(false);
                    }
                },
                error: function() {
                    self.updateSessionStatus(false);
                }
            });
        },

        /**
         * Met à jour l'indicateur de session
         */
        updateSessionStatus: function(connected) {
            if (!this.$sessionStatus.length) return;

            if (connected) {
                this.$sessionStatus.removeClass('disconnected');
                this.$sessionStatus.find('span:last').text(slidemindAdmin.strings.sessionActive);
            } else {
                this.$sessionStatus.addClass('disconnected');
                this.$sessionStatus.find('span:last').text(slidemindAdmin.strings.sessionInactive);
            }
        },

        /**
         * Affiche une notice de restauration
         */
        showRestoredNotice: function() {
            var $notice = $('<div class="sm-restored-notice"><span class="dashicons dashicons-backup"></span>' + slidemindAdmin.strings.conversationRestored + '</div>');
            this.$messagesContainer.before($notice);

            setTimeout(function() {
                $notice.fadeOut(function() {
                    $(this).remove();
                });
            }, 5000);
        },

        /**
         * Rend la conversation restaurée
         */
        renderConversation: function() {
            // Clear empty state
            $('.sm-sandbox-empty').remove();

            // Render all messages
            for (var i = 0; i < this.messages.length; i++) {
                this.addMessageToUI(this.messages[i].role, this.messages[i].content, false);
            }

            this.scrollToBottom();
        },

        /**
         * Change le mode (config/manual)
         */
        setMode: function(mode) {
            this.currentMode = mode;

            $('.sm-sandbox-mode').removeClass('active').addClass('sm-btn-secondary');
            $('.sm-sandbox-mode[data-mode="' + mode + '"]').addClass('active').removeClass('sm-btn-secondary');

            $('#sm-sandbox-mode-config').toggle(mode === 'config');
            $('#sm-sandbox-mode-manual').toggle(mode === 'manual');

            // Toggle prompt display vs editor
            $('#sm-sandbox-prompt-display').toggle(mode === 'config');
            $('#sm-sandbox-prompt-editor').toggle(mode === 'manual');

            this.updateInputState();
            this.updateConfigActions();

            // Sync variables when switching to manual mode
            if (mode === 'manual') {
                this.syncVariablesFromPrompt();
            }
        },

        /**
         * Lit un data attribute de manière fiable (évite le cache jQuery .data())
         */
        readAttr: function($el, name) {
            return $el.attr('data-' + name) || '';
        },

        /**
         * Parse du JSON depuis un data attribute (avec fallback)
         */
        readAttrJSON: function($el, name, fallback) {
            var raw = $el.attr('data-' + name);
            if (!raw) return fallback || [];
            try {
                return JSON.parse(raw);
            } catch (e) {
                return fallback || [];
            }
        },

        loadConfigData: function($select) {
            var $option = $select.find(':selected');

            // Use .attr() instead of .data() to avoid jQuery caching/auto-parsing issues
            var promptText = this.readAttr($option, 'prompt');
            var modelId = this.readAttr($option, 'model');
            var temperature = parseFloat(this.readAttr($option, 'temperature')) || 0.7;
            var maxTokens = parseInt(this.readAttr($option, 'max-tokens'), 10) || 1024;
            var variables = this.readAttrJSON($option, 'variables', []);
            var variableValues = this.readAttrJSON($option, 'variable-values', {});
            var outputVars = this.readAttrJSON($option, 'output-variables', []);
            var responseExample = this.readAttr($option, 'response-example');

            // Store source post ID and original values for change tracking
            var postId = this.readAttr($option, 'post-id');
            this.sourcePostId = postId ? parseInt(postId, 10) : null;
            this.originalValues = {
                model: modelId,
                prompt: promptText,
                temperature: temperature,
                maxTokens: maxTokens,
                outputVariables: JSON.stringify(outputVars),
                responseExample: responseExample
            };

            // Populate response example field
            $('#sm-sandbox-response-example').val(responseExample);

            // Populate manual mode fields (for export)
            $('#sm-sandbox-prompt').val(promptText);
            $('#sm-sandbox-model').val(modelId);
            $('#sm-sandbox-temperature').val(temperature);
            $('#sm-sandbox-temp-value').text(temperature);

            // Prompt display (read-only pre below chat)
            var $promptDisplay = $('#sm-sandbox-prompt-display-content');
            if (promptText) {
                $promptDisplay.text(promptText);
            } else {
                $promptDisplay.text(slidemindAdmin.strings.selectConfigPrompt);
            }

            // Info bar (model, temp, max tokens)
            var $infoBar = $('#sm-sandbox-prompt-info');
            if ($option.val()) {
                var modelShort = modelId.indexOf('/') !== -1 ? modelId.split('/').pop() : modelId;
                $('#sm-sandbox-info-model .sm-prompt-badge-text').text(modelShort);
                $('#sm-sandbox-info-temp .sm-prompt-badge-text').text('Temp: ' + temperature);
                $('#sm-sandbox-info-tokens .sm-prompt-badge-text').text(maxTokens + ' tokens');
                $infoBar.show();
            } else {
                $infoBar.hide();
            }

            // Auto-populate input variable rows from config prompt
            var $container = $('#sm-sandbox-variables');
            $container.find('.sm-sandbox-var-row, .sm-form-help').remove();

            if (variables.length > 0) {
                for (var i = 0; i < variables.length; i++) {
                    var varName = variables[i];
                    var prefilledValue = variableValues[varName] || '';
                    var isMultiline = prefilledValue.indexOf('\n') !== -1;
                    var displayValue = isMultiline ? prefilledValue.replace(/\n/g, ' ').substring(0, 80) + '…' : prefilledValue;
                    var fullValueAttr = isMultiline ? ' data-full-value="' + this.escapeAttr(prefilledValue) + '"' : '';
                    var html = '<div class="sm-form-group sm-sandbox-var-row">' +
                        '<div style="display: flex; gap: 8px;">' +
                        '<input type="text" class="sm-form-input sm-sandbox-var-name" value="' + this.escapeAttr(varName) + '" readonly style="width: 40%; background: #f3f4f6;">' +
                        '<input type="text" class="sm-form-input sm-sandbox-var-value" value="' + this.escapeAttr(displayValue) + '" placeholder="' + slidemindAdmin.strings.colValue + '" style="flex: 1;"' + fullValueAttr + '>' +
                        '<button type="button" class="sm-btn sm-btn-sm sm-btn-secondary sm-sandbox-var-expand" title="' + slidemindAdmin.strings.buttonExpand + '">' +
                        '<span class="dashicons dashicons-editor-expand"></span>' +
                        '</button>' +
                        '<button type="button" class="sm-btn sm-btn-sm sm-btn-secondary sm-sandbox-var-remove">' +
                        '<span class="dashicons dashicons-no-alt"></span>' +
                        '</button>' +
                        '</div></div>';
                    $container.append(html);
                }
            } else {
                $container.html('<p class="sm-form-help" style="color: #9ca3af;">' + slidemindAdmin.strings.noVarsDetected + '</p>');
            }

            // Populate output variables repeater
            this.populateOutputVariables(outputVars);

            this.updateConfigActions();
        },

        /**
         * Met à jour l'état des inputs
         */
        updateInputState: function() {
            var hasConfig = this.currentMode === 'manual' || $('#sm-sandbox-config').val();
            this.$inputField.prop('disabled', !hasConfig);
            this.$sendButton.prop('disabled', !hasConfig);
        },

        /**
         * Ajoute une ligne de variable (optionnel: nom pré-rempli et readonly)
         */
        addVariableRow: function(varName) {
            var nameVal = varName ? ' value="' + this.escapeAttr(varName) + '" readonly style="width: 40%; background: #f3f4f6;"' : ' placeholder="' + slidemindAdmin.strings.colVariable + '" style="width: 40%;"';
            var html = '<div class="sm-form-group sm-sandbox-var-row">' +
                '<div style="display: flex; gap: 8px;">' +
                '<input type="text" class="sm-form-input sm-sandbox-var-name"' + nameVal + '>' +
                '<input type="text" class="sm-form-input sm-sandbox-var-value" placeholder="' + slidemindAdmin.strings.colValue + '" style="flex: 1;">' +
                '<button type="button" class="sm-btn sm-btn-sm sm-btn-secondary sm-sandbox-var-expand" title="' + slidemindAdmin.strings.buttonExpand + '">' +
                '<span class="dashicons dashicons-editor-expand"></span>' +
                '</button>' +
                '<button type="button" class="sm-btn sm-btn-sm sm-btn-secondary sm-sandbox-var-remove">' +
                '<span class="dashicons dashicons-no-alt"></span>' +
                '</button>' +
                '</div></div>';
            $('#sm-sandbox-variables').append(html);
        },

        /**
         * Supprime une ligne de variable
         */
        removeVariableRow: function($row) {
            $row.remove();
        },

        /**
         * Synchronise les variables de test depuis le prompt système
         */
        syncVariablesFromPrompt: function() {
            var promptText = $('#sm-sandbox-prompt').val() || '';
            var regex = /\{\{([\w.]+)\}\}/g;
            var match;
            var promptVars = [];

            while ((match = regex.exec(promptText)) !== null) {
                if (promptVars.indexOf(match[1]) === -1) {
                    promptVars.push(match[1]);
                }
            }

            var $container = $('#sm-sandbox-variables');

            // Collect existing rows keyed by name
            var existing = {};
            $container.find('.sm-sandbox-var-row').each(function() {
                var name = $(this).find('.sm-sandbox-var-name').val().trim();
                if (name) {
                    existing[name] = $(this);
                }
            });

            // Remove rows whose variable is no longer in the prompt
            for (var name in existing) {
                if (existing.hasOwnProperty(name) && promptVars.indexOf(name) === -1) {
                    existing[name].remove();
                }
            }

            // Add rows for new variables (preserve existing ones)
            for (var i = 0; i < promptVars.length; i++) {
                if (!existing[promptVars[i]]) {
                    this.addVariableRow(promptVars[i]);
                }
            }

            // If no variables at all, show empty state
            if (promptVars.length === 0 && $container.find('.sm-sandbox-var-row').length === 0) {
                $container.html('<p class="sm-form-help" style="color: #9ca3af;">' + slidemindAdmin.strings.noVarsDetected + '</p>');
            } else {
                $container.find('.sm-form-help').remove();
            }
        },

        /**
         * Collecte les variables
         */
        collectVariables: function() {
            var variables = {};
            $('.sm-sandbox-var-row').each(function() {
                var name = $(this).find('.sm-sandbox-var-name').val().trim();
                var $input = $(this).find('.sm-sandbox-var-value');
                var fullValue = $input.attr('data-full-value');
                var value = fullValue ? fullValue : $input.val().trim();
                if (name && value) {
                    variables[name] = value;
                }
            });
            return variables;
        },

        /**
         * Ajoute une ligne de variable de retour
         */
        addOutputVariableRow: function(data) {
            data = data || {};
            var type = data.type || 'texte';
            var enumStyle = type === 'enum' ? '' : 'display:none;';
            var hints = { booleen: slidemindAdmin.strings.hintBooleanShort, nombre: slidemindAdmin.strings.hintNumberShort };
            var hintHtml = hints[type] ? '<span class="sm-sandbox-output-var-type-hint">' + hints[type] + '</span>' : '';

            var placeholders = {
                texte: slidemindAdmin.strings.placeholderDescOptional,
                nombre: slidemindAdmin.strings.placeholderDescNumber,
                booleen: slidemindAdmin.strings.placeholderDescCondition,
                enum: slidemindAdmin.strings.placeholderDescOptional
            };

            var valuesStr = '';
            if (data.values) {
                valuesStr = Array.isArray(data.values) ? data.values.join(', ') : data.values;
            }

            var html = '<div class="sm-sandbox-output-var-row">' +
                '<div class="sm-sandbox-output-var-fields">' +
                '<input type="text" class="sm-form-input sm-sandbox-output-var-name" value="' + this.escapeAttr(data.name || '') + '" placeholder="nom_variable" pattern="^[a-z][a-z0-9_]*$" title="' + slidemindAdmin.strings.outputVarNameTitle + '">' +
                '<div class="sm-sandbox-output-var-type-wrap">' +
                '<select class="sm-form-select sm-sandbox-output-var-type">' +
                '<option value="texte"' + (type === 'texte' ? ' selected' : '') + '>' + slidemindAdmin.strings.typeText + '</option>' +
                '<option value="nombre"' + (type === 'nombre' ? ' selected' : '') + '>' + slidemindAdmin.strings.typeNumber + '</option>' +
                '<option value="booleen"' + (type === 'booleen' ? ' selected' : '') + '>' + slidemindAdmin.strings.typeBoolean + '</option>' +
                '<option value="enum"' + (type === 'enum' ? ' selected' : '') + '>Enum</option>' +
                '</select>' +
                hintHtml +
                '</div>' +
                '<input type="text" class="sm-form-input sm-sandbox-output-var-desc" value="' + this.escapeAttr(data.description || '') + '" placeholder="' + (placeholders[type] || slidemindAdmin.strings.placeholderDescOptional) + '">' +
                '<button type="button" class="sm-btn sm-btn-sm sm-btn-danger sm-sandbox-output-var-remove" title="' + slidemindAdmin.strings.buttonDelete + '">' +
                '<span class="dashicons dashicons-no-alt"></span>' +
                '</button>' +
                '</div>' +
                (valuesStr ? '<input type="text" class="sm-form-input sm-sandbox-output-var-values" value="' + this.escapeAttr(valuesStr) + '" placeholder="val1, val2, val3">' : '<input type="text" class="sm-form-input sm-sandbox-output-var-values" placeholder="val1, val2, val3" style="' + enumStyle + '">') +
                '</div>';

            $('#sm-sandbox-output-vars-list').append(html);
        },

        /**
         * Remplit le repeater de variables de retour
         */
        populateOutputVariables: function(vars) {
            var $list = $('#sm-sandbox-output-vars-list');
            $list.empty();

            if (!vars || !Array.isArray(vars) || vars.length === 0) {
                return;
            }

            for (var i = 0; i < vars.length; i++) {
                this.addOutputVariableRow(vars[i]);
            }
        },

        /**
         * Collecte les variables de retour du sandbox
         */
        collectOutputVariables: function() {
            var variables = [];
            $('#sm-sandbox-output-vars-list .sm-sandbox-output-var-row').each(function() {
                var $row = $(this);
                var name = $row.find('.sm-sandbox-output-var-name').val().trim();
                if (!name) return;

                var type = $row.find('.sm-sandbox-output-var-type').val();
                var entry = {
                    name: name,
                    type: type,
                    description: $row.find('.sm-sandbox-output-var-desc').val().trim()
                };

                if (type === 'enum') {
                    var valStr = $row.find('.sm-sandbox-output-var-values').val().trim();
                    if (valStr) {
                        entry.values = valStr.split(',').map(function(v) { return v.trim(); }).filter(function(v) { return v !== ''; });
                    }
                }

                variables.push(entry);
            });
            return variables;
        },

        /**
         * Envoie un message (both modes use sandbox/test endpoint)
         */
        sendMessage: function() {
            var self = this;
            var userMessage = this.$inputField.val().trim();

            if (!userMessage) return;

            // Clear empty state
            $('.sm-sandbox-empty').remove();

            // Add user message
            this.messages.push({ role: 'user', content: userMessage });
            this.addMessageToUI('user', userMessage);

            this.$inputField.val('').focus();

            // Show typing indicator
            this.showTypingIndicator();

            var startTime = Date.now();
            var variables = this.collectVariables();
            var outputVariables = this.collectOutputVariables();

            // Build request — always use sandbox/test endpoint
            var endpoint = slidemindAdmin.restUrl + 'sandbox/test';
            var requestData;

            if (this.currentMode === 'config') {
                var $option = $('#sm-sandbox-config option:selected');
                requestData = {
                    model: this.readAttr($option, 'model'),
                    system_prompt: this.readAttr($option, 'prompt'),
                    temperature: parseFloat(this.readAttr($option, 'temperature')) || 0.7,
                    max_tokens: parseInt(this.readAttr($option, 'max-tokens'), 10) || 1024,
                    messages: this.messages,
                    variables: variables,
                    output_variables: outputVariables,
                    response_example: this.readAttr($option, 'response-example'),
                    session_id: this.sessionId
                };
            } else {
                requestData = {
                    model: $('#sm-sandbox-model').val(),
                    system_prompt: $('#sm-sandbox-prompt').val(),
                    temperature: parseFloat($('#sm-sandbox-temperature').val()),
                    max_tokens: parseInt($('#sm-sandbox-max-tokens').val()) || 1024,
                    messages: this.messages,
                    variables: variables,
                    output_variables: outputVariables,
                    response_example: $('#sm-sandbox-response-example').val() || '',
                    session_id: this.sessionId,
                    provider: $('#sm-sandbox-provider').val() || ''
                };
            }

            $.ajax({
                url: endpoint,
                method: 'POST',
                contentType: 'application/json',
                headers: {
                    'X-WP-Nonce': slidemindAdmin.restNonce
                },
                data: JSON.stringify(requestData),
                success: function(response) {
                    self.hideTypingIndicator();

                    if (response.success) {
                        self.messages.push(response.message);
                        self.addMessageToUI('assistant', response.message.content);
                        self.updateDebugPanel(response, Date.now() - startTime);

                        // Show rendered prompt if available
                        if (response.debug) {
                            self.showRenderedPrompt(response.debug);
                        }

                        // Show structured data if available
                        if (response.structured_data) {
                            self.showStructuredData(response.structured_data, response.structured);
                        }

                        // Save session
                        self.saveSession();
                    } else {
                        self.addMessageToUI('error', slidemindAdmin.strings.errorPrefix + (response.error || slidemindAdmin.strings.unknownError));
                    }
                },
                error: function(xhr) {
                    self.hideTypingIndicator();
                    var errorMsg = slidemindAdmin.strings.connectionError;
                    if (xhr.responseJSON && xhr.responseJSON.message) {
                        errorMsg = xhr.responseJSON.message;
                    }
                    self.addMessageToUI('error', errorMsg);
                }
            });
        },

        /**
         * Sauvegarde la session
         */
        saveSession: function() {
            if (!this.sessionId) return;

            $.ajax({
                url: slidemindAdmin.ajaxUrl,
                method: 'POST',
                data: {
                    action: 'slidemind_sandbox_save_session',
                    nonce: slidemindAdmin.nonce,
                    session_id: this.sessionId,
                    messages: this.messages
                }
            });
        },

        /**
         * Efface la session
         */
        clearSession: function() {
            var self = this;

            $.ajax({
                url: slidemindAdmin.ajaxUrl,
                method: 'POST',
                data: {
                    action: 'slidemind_sandbox_clear_session',
                    nonce: slidemindAdmin.nonce
                },
                success: function(response) {
                    if (response.success) {
                        self.sessionId = response.data.session_id;
                    }
                }
            });

            // Reset local state
            this.messages = [];
            this.$messagesContainer.html(
                '<div class="sm-sandbox-empty" style="text-align: center; padding: 20px 40px; color: #6b7280;">' +
                '<span class="dashicons dashicons-format-chat" style="font-size: 36px; margin-bottom: 12px; display: block;"></span>' +
                '<p>' + slidemindAdmin.strings.conversationReset + '</p></div>'
            );
            this.$debugPanel.html('<p>' + slidemindAdmin.strings.debugSendMessage + '</p>');
            if (this.$promptDebug.length) {
                this.$promptDebug.html('');
            }
        },

        /**
         * Ajoute un message à l'UI
         */
        addMessageToUI: function(role, content, scroll) {
            scroll = scroll !== false;

            var avatarIcon = role === 'user' ? 'dashicons-admin-users' : 'dashicons-admin-generic';
            var $message = $(
                '<div class="sm-sandbox-message sm-sandbox-message-' + role + '">' +
                '<div class="sm-sandbox-message-avatar"><span class="dashicons ' + avatarIcon + '"></span></div>' +
                '<div class="sm-sandbox-message-content">' + this.escapeHtml(content) + '</div>' +
                '</div>'
            );

            if (role === 'error') {
                $message.find('.sm-sandbox-message-content').css({
                    background: '#fee2e2',
                    color: '#991b1b'
                });
            }

            this.$messagesContainer.append($message);

            if (scroll) {
                this.scrollToBottom();
            }
        },

        /**
         * Affiche l'indicateur de saisie
         */
        showTypingIndicator: function() {
            var $typing = $(
                '<div class="sm-sandbox-message sm-sandbox-message-assistant sm-sandbox-typing-container">' +
                '<div class="sm-sandbox-message-avatar"><span class="dashicons dashicons-admin-generic"></span></div>' +
                '<div class="sm-sandbox-message-content">' +
                '<div class="sm-sandbox-typing"><span></span><span></span><span></span></div>' +
                '</div></div>'
            );
            this.$messagesContainer.append($typing);
            this.scrollToBottom();
        },

        /**
         * Cache l'indicateur de saisie
         */
        hideTypingIndicator: function() {
            $('.sm-sandbox-typing-container').remove();
        },

        /**
         * Scroll vers le bas
         */
        scrollToBottom: function() {
            this.$messagesContainer.scrollTop(this.$messagesContainer[0].scrollHeight);
        },

        /**
         * Retourne un snapshot de la configuration courante pour la comparaison
         */
        getComparisonConfig: function() {
            var config = {};

            if (this.currentMode === 'config') {
                var $option = $('#sm-sandbox-config option:selected');
                config.model = this.readAttr($option, 'model');
                config.prompt = this.readAttr($option, 'prompt');
                config.temperature = parseFloat(this.readAttr($option, 'temperature')) || 0.7;
                config.max_tokens = parseInt(this.readAttr($option, 'max-tokens'), 10) || 1024;
                config.response_example = this.readAttr($option, 'response-example');
            } else {
                config.model = $('#sm-sandbox-model').val();
                config.prompt = $('#sm-sandbox-prompt').val();
                config.temperature = parseFloat($('#sm-sandbox-temperature').val()) || 0.7;
                config.max_tokens = parseInt($('#sm-sandbox-max-tokens').val(), 10) || 1024;
                config.response_example = $('#sm-sandbox-response-example').val() || '';
            }

            config.variables = this.collectVariables();
            config.output_variables = this.collectOutputVariables();

            // Last user message
            var lastUserMsg = '';
            for (var i = this.messages.length - 1; i >= 0; i--) {
                if (this.messages[i].role === 'user') {
                    lastUserMsg = this.messages[i].content;
                    break;
                }
            }
            config.lastMessage = lastUserMsg;

            return config;
        },

        /**
         * Met à jour le panel de debug
         */
        updateDebugPanel: function(response, clientTime) {
            if (!slidemindAdmin.proFeatures || !slidemindAdmin.proFeatures.full_sandbox) {
                return;
            }
            var s = slidemindAdmin.strings;
            var html = '<div class="sm-debug-section">';
            html += '<h4>' + s.debugRequestInfo + '</h4>';
            html += '<table class="sm-debug-table">';
            html += '<tr><td>' + s.debugModel + '</td><td><code>' + (response.meta && response.meta.model ? response.meta.model : 'N/A') + '</code></td></tr>';
            html += '<tr><td>' + s.debugTokensInput + '</td><td>' + (response.usage && response.usage.prompt_tokens ? response.usage.prompt_tokens : 0) + '</td></tr>';
            html += '<tr><td>' + s.debugTokensOutput + '</td><td>' + (response.usage && response.usage.completion_tokens ? response.usage.completion_tokens : 0) + '</td></tr>';
            html += '<tr><td>' + s.debugTokensTotal + '</td><td><strong>' + (response.usage && response.usage.total_tokens ? response.usage.total_tokens : 0) + '</strong></td></tr>';
            html += '<tr><td>' + s.debugResponseTime + '</td><td>' + (response.meta && response.meta.response_time ? response.meta.response_time : clientTime) + ' ms</td></tr>';
            html += '<tr><td>' + s.debugEstimatedCost + '</td><td>$' + this.formatCost(response.usage && response.usage.estimated_cost ? response.usage.estimated_cost : 0) + '</td></tr>';
            html += '</table>';

            // Comparison link (Pro feature)
            if (slidemindAdmin.proFeatures && slidemindAdmin.proFeatures.comparison) {
                html += '<div style="margin-top: 12px; text-align: right;">';
                html += '<a href="#" class="sm-comparison-debug-link" style="font-size: 13px; text-decoration: none; color: var(--sm-primary);">';
                html += '<span class="dashicons dashicons-randomize" style="font-size: 14px; width: 14px; height: 14px; vertical-align: middle;"></span> ';
                html += s.comparisonCompareOthers;
                html += '</a></div>';
            }

            html += '</div>';

            this.$debugPanel.html(html);
        },

        /**
         * Affiche le prompt rendu
         */
        showRenderedPrompt: function(debug) {
            if (!this.$promptDebug.length) return;
            if (!slidemindAdmin.proFeatures || !slidemindAdmin.proFeatures.full_sandbox) return;

            var s = slidemindAdmin.strings;
            var html = '<div class="sm-debug-section sm-prompt-debug">';
            html += '<h4>' + s.debugSystemPrompt + '</h4>';

            // Tabs
            html += '<div class="sm-tabs-mini">';
            html += '<button type="button" class="sm-tab-mini active" data-tab="original">' + s.tabOriginal + '</button>';
            html += '<button type="button" class="sm-tab-mini" data-tab="rendered">' + s.tabRendered + '</button>';
            html += '</div>';

            // Original
            html += '<div class="sm-tab-content-mini active" data-tab-content="original">';
            html += '<pre class="sm-prompt-preview">' + this.escapeHtml(debug.prompt_original || '') + '</pre>';
            html += '</div>';

            // Rendered
            html += '<div class="sm-tab-content-mini" data-tab-content="rendered">';
            html += '<pre class="sm-prompt-preview sm-prompt-rendered">' + this.escapeHtml(debug.prompt_rendered || '') + '</pre>';
            html += '</div>';

            // Variables used
            var varsUsed = debug.variables_used || {};
            if (Object.keys(varsUsed).length > 0) {
                html += '<div class="sm-variables-used">';
                html += '<strong>' + slidemindAdmin.strings.debugVarsInjected + '</strong> ';
                var vars = [];
                for (var key in varsUsed) {
                    if (varsUsed.hasOwnProperty(key)) {
                        vars.push('<code>{{' + key + '}}</code> = "' + this.escapeHtml(varsUsed[key]) + '"');
                    }
                }
                html += vars.join(', ');
                html += '</div>';
            }

            // Missing variables
            var varsMissing = debug.variables_missing || [];
            if (varsMissing.length > 0) {
                html += '<div class="sm-variables-missing">';
                html += '<strong>' + slidemindAdmin.strings.debugVarsMissing + '</strong> ';
                var missing = [];
                for (var i = 0; i < varsMissing.length; i++) {
                    missing.push('<code>{{' + varsMissing[i] + '}}</code>');
                }
                html += missing.join(', ');
                html += '</div>';
            }

            html += '</div>';

            this.$promptDebug.html(html);
        },

        /**
         * Affiche les données structurées dans le debug
         */
        showStructuredData: function(data, isValid) {
            if (!this.$promptDebug.length) return;

            var html = '<div class="sm-debug-section">';
            html += '<h4>' + slidemindAdmin.strings.debugStructuredResponse + '</h4>';
            if (!isValid) {
                html += '<div class="sm-variables-missing" style="margin-top:0; margin-bottom:8px;"><strong>' + slidemindAdmin.strings.debugPartialParsing + '</strong> — ' + slidemindAdmin.strings.debugPartialParsingDesc + '</div>';
            }
            html += '<pre class="sm-prompt-preview" style="max-height:150px;">' + this.escapeHtml(JSON.stringify(data, null, 2)) + '</pre>';
            html += '</div>';

            this.$promptDebug.append(html);
        },

        /**
         * Exporte la configuration
         */
        exportConfig: function() {
            var self = this;
            var config;

            if (this.currentMode === 'config') {
                var $option = $('#sm-sandbox-config option:selected');
                config = {
                    config_id: $option.val(),
                    title: $option.text().trim(),
                    model_id: this.readAttr($option, 'model'),
                    system_prompt: this.readAttr($option, 'prompt'),
                    temperature: parseFloat(this.readAttr($option, 'temperature')) || 0.7,
                    max_tokens: parseInt(this.readAttr($option, 'max-tokens'), 10) || 1024,
                    response_example: this.readAttr($option, 'response-example')
                };
            } else {
                config = {
                    model_id: $('#sm-sandbox-model').val(),
                    system_prompt: $('#sm-sandbox-prompt').val(),
                    temperature: parseFloat($('#sm-sandbox-temperature').val()),
                    max_tokens: parseInt($('#sm-sandbox-max-tokens').val()) || 1024,
                    response_example: $('#sm-sandbox-response-example').val() || ''
                };
            }

            config.variables = this.collectVariables();
            config.output_variables = this.collectOutputVariables();
            config.conversation = this.messages;

            // Use AJAX to generate export
            $.ajax({
                url: slidemindAdmin.ajaxUrl,
                method: 'POST',
                data: {
                    action: 'slidemind_sandbox_export_config',
                    nonce: slidemindAdmin.nonce,
                    model_id: config.model_id,
                    system_prompt: config.system_prompt,
                    temperature: config.temperature,
                    max_tokens: config.max_tokens,
                    variables: config.variables,
                    output_variables: config.output_variables,
                    conversation: config.conversation
                },
                success: function(response) {
                    if (response.success) {
                        self.downloadJSON(response.data.json, response.data.filename);
                    } else {
                        alert(slidemindAdmin.strings.exportError);
                    }
                },
                error: function() {
                    alert(slidemindAdmin.strings.exportError);
                }
            });
        },

        /**
         * Télécharge un fichier JSON
         */
        downloadJSON: function(jsonString, filename) {
            var blob = new Blob([jsonString], { type: 'application/json' });
            var url = URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        },

        /**
         * Formate le coût
         */
        formatCost: function(cost) {
            return parseFloat(cost).toFixed(6);
        },

        /**
         * Escape HTML
         */
        escapeHtml: function(text) {
            if (!text) return '';
            return $('<div>').text(text).html().replace(/\n/g, '<br>');
        },

        /**
         * Met à jour la visibilité des boutons d'action config
         */
        updateConfigActions: function() {
            var $actions = $('#sm-sandbox-config-actions');
            var $editLink = $('#sm-sandbox-edit-slide');
            var $applyBtn = $('#sm-sandbox-apply-changes');

            if (!this.sourcePostId) {
                $actions.css('display', 'none');
                return;
            }

            // Update edit link
            $editLink.attr('href', 'admin.php?page=slidemind-slide-edit&slide_id=' + this.sourcePostId);
            $actions.css('display', 'flex');

            // Show/hide apply button based on changes
            if (this.currentMode === 'manual' && this.hasChanges()) {
                $applyBtn.css('display', 'inline-flex');
            } else {
                $applyBtn.css('display', 'none');
            }
        },

        /**
         * Vérifie si des modifications ont été faites par rapport aux valeurs originales
         */
        hasChanges: function() {
            if (!this.originalValues) return false;

            var current = {
                model: $('#sm-sandbox-model').val() || '',
                prompt: $('#sm-sandbox-prompt').val() || '',
                temperature: parseFloat($('#sm-sandbox-temperature').val()) || 0.7,
                maxTokens: parseInt($('#sm-sandbox-max-tokens').val(), 10) || 1024,
                outputVariables: JSON.stringify(this.collectOutputVariables()),
                responseExample: $('#sm-sandbox-response-example').val() || ''
            };

            return current.model !== this.originalValues.model ||
                   current.prompt !== this.originalValues.prompt ||
                   current.temperature !== this.originalValues.temperature ||
                   current.maxTokens !== this.originalValues.maxTokens ||
                   current.outputVariables !== this.originalValues.outputVariables ||
                   current.responseExample !== (this.originalValues.responseExample || '');
        },

        /**
         * Applique les modifications du sandbox vers la slide source
         */
        applyChanges: function() {
            if (!this.sourcePostId) return;

            if (!confirm(slidemindAdmin.strings.confirmApplyChanges)) {
                return;
            }

            var self = this;
            var $option = $('#sm-sandbox-config option:selected');
            var title = $option.text().trim();
            var outputVars = this.collectOutputVariables();

            var responseExample = $('#sm-sandbox-response-example').val() || '';

            var slide = {
                id: this.sourcePostId,
                title: title,
                model_id: $('#sm-sandbox-model').val(),
                system_prompt: $('#sm-sandbox-prompt').val(),
                temperature: parseFloat($('#sm-sandbox-temperature').val()) || 0.7,
                max_tokens: parseInt($('#sm-sandbox-max-tokens').val(), 10) || 1024,
                output_variables: outputVars,
                response_example: responseExample
            };

            SM.Utils.ajax('slidemind_save_slide', { slide: slide }, function(response) {
                if (response.success) {
                    // Update original values
                    self.originalValues = {
                        model: slide.model_id,
                        prompt: slide.system_prompt,
                        temperature: slide.temperature,
                        maxTokens: slide.max_tokens,
                        outputVariables: JSON.stringify(outputVars),
                        responseExample: responseExample
                    };

                    // Sync data attributes on the option
                    $option.attr('data-model', slide.model_id);
                    $option.attr('data-prompt', slide.system_prompt);
                    $option.attr('data-temperature', slide.temperature);
                    $option.attr('data-max-tokens', slide.max_tokens);
                    $option.attr('data-output-variables', JSON.stringify(outputVars));
                    $option.attr('data-response-example', responseExample);

                    // Hide apply button
                    $('#sm-sandbox-apply-changes').css('display', 'none');

                    SM.Utils.showToast(slidemindAdmin.strings.changesApplied, 'success');
                } else {
                    SM.Utils.showToast(response.data.message || slidemindAdmin.strings.saveError, 'error');
                }
            });
        },

        /**
         * Construit le modal d'expand pour les variables
         */
        buildVarExpandModal: function() {
            if ($('#sm-var-expand-modal').length) return;

            var html = '<div id="sm-var-expand-modal" class="sm-modal-overlay" data-custom-close="true">' +
                '<div class="sm-modal" style="max-width: 600px;">' +
                '<div class="sm-modal-header">' +
                '<h3 class="sm-modal-title" id="sm-var-expand-title">Variable</h3>' +
                '<button type="button" class="sm-modal-close">&times;</button>' +
                '</div>' +
                '<div class="sm-modal-body">' +
                '<textarea id="sm-var-expand-textarea" class="sm-form-textarea" rows="10"></textarea>' +
                '<div style="text-align: right;">' +
                '<button type="button" id="sm-var-expand-ok" class="sm-btn sm-btn-primary">' + slidemindAdmin.strings.validateButton + '</button>' +
                '</div>' +
                '</div>' +
                '</div></div>';

            $('body').append(html);
        },

        /**
         * Ouvre le modal d'expand pour une variable
         */
        openVarExpandModal: function($row) {
            this._expandRow = $row;
            var $input = $row.find('.sm-sandbox-var-value');
            var varName = $row.find('.sm-sandbox-var-name').val() || slidemindAdmin.strings.colVariable;
            var fullValue = $input.attr('data-full-value') || $input.val();

            $('#sm-var-expand-title').text(varName);
            $('#sm-var-expand-textarea').val(fullValue);
            $('#sm-var-expand-modal').addClass('active');
            $('body').css('overflow', 'hidden');

            // Focus textarea
            setTimeout(function() {
                $('#sm-var-expand-textarea').focus();
            }, 100);
        },

        /**
         * Ferme le modal d'expand (avec ou sans sauvegarde)
         */
        closeVarExpandModal: function(save) {
            if (save && this._expandRow) {
                var newValue = $('#sm-var-expand-textarea').val();
                var $input = this._expandRow.find('.sm-sandbox-var-value');
                var isMultiline = newValue.indexOf('\n') !== -1;

                if (isMultiline) {
                    $input.attr('data-full-value', newValue);
                    var flat = newValue.replace(/\n/g, ' ').substring(0, 80);
                    $input.val(flat + (newValue.length > 80 ? '…' : ''));
                } else {
                    $input.removeAttr('data-full-value');
                    $input.val(newValue);
                }
            }

            this._expandRow = null;
            $('#sm-var-expand-modal').removeClass('active');
            $('body').css('overflow', '');
        },

        /**
         * Escape attribute value (includes double quotes)
         */
        escapeAttr: function(text) {
            if (!text) return '';
            return String(text).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        }
    };

    // Initialize on document ready
    $(document).ready(function() {
        // Only init if we're on the sandbox page
        if ($('#sm-sandbox-messages').length) {
            SM.Sandbox.init();
        }
    });

})(jQuery);
