/**
 * GriffinForms Theme Editor JavaScript
 * Handles form submission, AJAX requests, and state management
 */

(function($) {
    'use strict';

    const GriffinFormsTheme = {
        /**
         * Initialize the theme editor
         */
        init: function() {
            this.cacheElements();
            this.bindEvents();
            this.initColorPickers();
            this.initMediaPickers();
        },

        /**
         * Cache jQuery elements for reuse
         */
        cacheElements: function() {
            this.$document = $(document);
            this.$saveButton = $('#griffinforms-create-item, #griffinforms-update-item');
            this.$colorPickers = $('.griffinforms-color-picker, .griffinforms-shadow-color-picker');
            this.$colorValues = $('.griffinforms-color-value, .griffinforms-shadow-color-value');
            this.$dimensionInputs = $('.griffinforms-dimension-input, .griffinforms-side-dimension, .griffinforms-shadow-dimension');
        },

        /**
         * Bind event handlers
         */
        bindEvents: function() {
            const self = this;

            // Color picker sync
            this.$colorPickers.on('change', function() {
                self.syncColorValue($(this));
            });

            // Color value input sync
            this.$colorValues.on('change', function() {
                self.syncColorPicker($(this));
            });

            // Dimension input validation
            this.$dimensionInputs.on('blur', function() {
                self.validateDimensionInput($(this));
            });

            // Unit selection - update hidden value when unit changes
            $(document).on('change', '.griffinforms-dimension-unit', function() {
                self.updateDimensionValue($(this));
            });

            // Update hidden value when numeric value changes
            this.$dimensionInputs.on('change', function() {
                self.updateDimensionValue($(this));
            });

            // Background mode radio button (Single Color vs Gradient vs Image)
            $(document).on('change', '.griffinforms-background-mode-radio', function() {
                const $radio = $(this);
                const backgroundName = $radio.data('background-name');
                const mode = $radio.val(); // 'single', 'gradient', or 'image'

                // Find the parent background control
                const $backgroundControl = $radio.closest('.griffinforms-background-control');

                if (mode === 'single') {
                    // Show single color field, hide gradient and image fields
                    $backgroundControl.find('.griffinforms-background-single-color').slideDown(200);
                    $backgroundControl.find('.griffinforms-background-gradient-color-1').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-gradient-color-2').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-gradient-angle').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-uploader').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-size').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-position').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-repeat').slideUp(200);
                } else if (mode === 'gradient') {
                    // Show gradient fields, hide single color and image fields
                    $backgroundControl.find('.griffinforms-background-single-color').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-gradient-color-1').slideDown(200);
                    $backgroundControl.find('.griffinforms-background-gradient-color-2').slideDown(200);
                    $backgroundControl.find('.griffinforms-background-gradient-angle').slideDown(200);
                    $backgroundControl.find('.griffinforms-background-image-uploader').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-size').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-position').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-repeat').slideUp(200);
                } else if (mode === 'image') {
                    // Show image fields, hide single color and gradient fields
                    $backgroundControl.find('.griffinforms-background-single-color').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-gradient-color-1').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-gradient-color-2').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-gradient-angle').slideUp(200);
                    $backgroundControl.find('.griffinforms-background-image-uploader').slideDown(200);
                    $backgroundControl.find('.griffinforms-background-image-size').slideDown(200);
                    $backgroundControl.find('.griffinforms-background-image-position').slideDown(200);
                    $backgroundControl.find('.griffinforms-background-image-repeat').slideDown(200);
                }
            });

            // Button copy functionality
            $(document).on('click', '.griffinforms-copy-to-button', function(e) {
                e.preventDefault();
                const sourceButton = $(this).data('source-button');
                const targetButton = $(this).data('target-button');
                self.copyButtonStyles(sourceButton, targetButton);
            });

            // Form save
            this.$saveButton.on('click', function(e) {
                e.preventDefault();
                self.saveTheme();
            });
        },

        /**
         * Initialize Spectrum.js color pickers with RGBA support
         */
        initColorPickers: function() {
            const self = this;

            // Check if Spectrum.js is loaded
            if (typeof jQuery.fn.spectrum !== 'function') {
                console.warn('Spectrum.js not loaded. Color picker functionality disabled.');
                return;
            }

            // Initialize Spectrum.js on all color picker inputs
            $('.griffinforms-color-picker').spectrum({
                type: 'component',
                showInput: true,
                showAlpha: true,
                showPalette: true,
                preferredFormat: 'rgb',
                allowEmpty: false,
                containerClassName: 'spectrum-container',
                replacerClassName: 'spectrum-replacer',
                palette: [
                    // Basic colors + Blues
                    ['#000000', '#ffffff', '#ff0000', '#00ff00', '#0000ff', '#003087', '#0052cc', '#0066ff'],
                    // Blues continued + Grays
                    ['#3385ff', '#66a3ff', '#99c2ff', '#1f2937', '#374151', '#6b7280', '#9ca3af', '#d1d5db'],
                    // Grays continued + Reds
                    ['#e5e7eb', '#f3f4f6', '#f9fafb', '#7f1d1d', '#991b1b', '#dc2626', '#ef4444', '#f87171'],
                    // Reds continued + Greens
                    ['#fca5a5', '#14532d', '#166534', '#15803d', '#22c55e', '#86efac', '#bbf7d0', '#78350f'],
                    // Yellows & Oranges + Purples
                    ['#b45309', '#f59e0b', '#fbbf24', '#fcd34d', '#fef3c7', '#581c87', '#7e22ce', '#a855f7'],
                    // Purples & Pinks continued
                    ['#d946ef', '#f472b6', '#fbcfe8'],
                    // Transparent colors (helpful for glassmorphism & shadows)
                    ['rgba(255, 255, 255, 0.95)', 'rgba(255, 255, 255, 0.9)', 'rgba(255, 255, 255, 0.7)', 'rgba(255, 255, 255, 0.5)', 'rgba(0, 0, 0, 0.3)', 'rgba(0, 0, 0, 0.2)', 'rgba(0, 0, 0, 0.1)', 'rgba(0, 0, 0, 0.05)']
                ],
                change: function(color) {
                    // Update the color picker value with current color
                    const colorString = color ? color.toRgbString() : '#000000';
                    $(this).val(colorString);

                    // Trigger change event for form tracking
                    $(this).trigger('change');

                    // Sync with any linked text input
                    const fieldName = $(this).data('field-name');
                    if (fieldName) {
                        const $linkedInput = $('input[data-linked-color-picker="' + fieldName + '"]');
                        if ($linkedInput.length) {
                            $linkedInput.val(colorString);
                        }
                    }
                },
                move: function(color) {
                    // Live preview as user drags
                    const colorString = color ? color.toRgbString() : '#000000';
                    $(this).val(colorString);
                },
                hide: function(color) {
                    // Final update when picker closes
                    const colorString = color ? color.toRgbString() : '#000000';
                    $(this).val(colorString).trigger('change');
                }
            });

            console.log('Spectrum.js color pickers initialized on ' + $('.griffinforms-color-picker').length + ' elements');

            // Initialize background color picker visibility based on gradient toggle state
            this.initializeGradientVisibility();
        },

        /**
         * Initialize visibility of background fields based on radio button state
         * Sets initial visibility for Single Color vs Gradient vs Image modes
         */
        initializeGradientVisibility: function() {
            $('.griffinforms-background-control').each(function() {
                const $control = $(this);
                const $selectedRadio = $control.find('.griffinforms-background-mode-radio:checked');

                if ($selectedRadio.length) {
                    const mode = $selectedRadio.val(); // 'single', 'gradient', or 'image'

                    if (mode === 'single') {
                        // Show single color field, hide gradient and image fields
                        $control.find('.griffinforms-background-single-color').show();
                        $control.find('.griffinforms-background-gradient-color-1').hide();
                        $control.find('.griffinforms-background-gradient-color-2').hide();
                        $control.find('.griffinforms-background-gradient-angle').hide();
                        $control.find('.griffinforms-background-image-uploader').hide();
                        $control.find('.griffinforms-background-image-size').hide();
                        $control.find('.griffinforms-background-image-position').hide();
                        $control.find('.griffinforms-background-image-repeat').hide();
                    } else if (mode === 'gradient') {
                        // Show gradient fields, hide single color and image fields
                        $control.find('.griffinforms-background-single-color').hide();
                        $control.find('.griffinforms-background-gradient-color-1').show();
                        $control.find('.griffinforms-background-gradient-color-2').show();
                        $control.find('.griffinforms-background-gradient-angle').show();
                        $control.find('.griffinforms-background-image-uploader').hide();
                        $control.find('.griffinforms-background-image-size').hide();
                        $control.find('.griffinforms-background-image-position').hide();
                        $control.find('.griffinforms-background-image-repeat').hide();
                    } else if (mode === 'image') {
                        // Show image fields, hide single color and gradient fields
                        $control.find('.griffinforms-background-single-color').hide();
                        $control.find('.griffinforms-background-gradient-color-1').hide();
                        $control.find('.griffinforms-background-gradient-color-2').hide();
                        $control.find('.griffinforms-background-gradient-angle').hide();
                        $control.find('.griffinforms-background-image-uploader').show();
                        $control.find('.griffinforms-background-image-size').show();
                        $control.find('.griffinforms-background-image-position').show();
                        $control.find('.griffinforms-background-image-repeat').show();
                    }
                }
            });
        },

        /**
         * Initialize WordPress Media Library pickers for background images
         */
        initMediaPickers: function() {
            const self = this;

            // Check if wp.media is available
            if (typeof wp === 'undefined' || typeof wp.media === 'undefined') {
                console.warn('WordPress media library not loaded. Image picker functionality disabled.');
                return;
            }

            // Handle "Choose Image" button clicks
            $(document).on('click', '.griffinforms-media-picker-btn', function(e) {
                e.preventDefault();

                const $button = $(this);
                const targetId = $button.data('target-id');
                const $hiddenInput = $('#' + targetId);

                // Create media frame
                const frame = wp.media({
                    title: 'Select Background Image',
                    button: {
                        text: 'Use this image'
                    },
                    multiple: false,
                    library: {
                        type: 'image'
                    }
                });

                // When image is selected
                frame.on('select', function() {
                    const attachment = frame.state().get('selection').first().toJSON();
                    const imageUrl = attachment.url;

                    // Update hidden input with image URL
                    $hiddenInput.val(imageUrl).trigger('change');

                    // Update/create preview container
                    const $wrapper = $button.closest('.griffinforms-media-picker-wrapper');
                    let $preview = $wrapper.find('.griffinforms-media-preview');

                    if ($preview.length === 0) {
                        // Create preview container
                        $preview = $('<div class="griffinforms-media-preview mb-2"></div>');
                        $button.before($preview);
                    }

                    // Update preview content
                    $preview.html(
                        '<img src="' + imageUrl + '" alt="Background Image" style="max-width: 100%; max-height: 150px; border-radius: 4px; border: 1px solid #ddd;" />' +
                        '<br/><small class="form-text text-muted d-block mt-2">' + imageUrl + '</small>'
                    ).show();

                    // Show/create remove button
                    let $removeBtn = $wrapper.find('.griffinforms-media-remove-btn');
                    if ($removeBtn.length === 0) {
                        $removeBtn = $('<button type="button" class="btn btn-sm btn-outline-danger griffinforms-media-remove-btn" data-target-id="' + targetId + '">Remove</button>');
                        $button.after(' ', $removeBtn);
                    }
                    $removeBtn.show();
                });

                // Open media frame
                frame.open();
            });

            // Handle "Remove Image" button clicks
            $(document).on('click', '.griffinforms-media-remove-btn', function(e) {
                e.preventDefault();

                const $button = $(this);
                const targetId = $button.data('target-id');
                const $hiddenInput = $('#' + targetId);

                // Clear hidden input
                $hiddenInput.val('').trigger('change');

                // Remove preview
                const $wrapper = $button.closest('.griffinforms-media-picker-wrapper');
                $wrapper.find('.griffinforms-media-preview').remove();

                // Hide remove button
                $button.hide();
            });
        },

        /**
         * Syncs color picker value to text input
         */
        syncColorValue: function($picker) {
            const linkedField = $picker.data('field-name');
            const $valueInput = $('input[data-linked-color-picker="' + linkedField + '"]');

            if ($valueInput.length) {
                $valueInput.val($picker.val());
            }
        },

        /**
         * Syncs color text input to picker (if valid)
         */
        syncColorPicker: function($input) {
            const linkedField = $input.data('linked-color-picker');
            const $picker = $('input[data-field-name="' + linkedField + '"][type="color"]');

            if ($picker.length && this.isValidColor($input.val())) {
                $picker.val(this.normalizeColorToHex($input.val()));
            }
        },

        /**
         * Validates dimension input (allows px, em, %, rem, etc.)
         */
        validateDimensionInput: function($input) {
            const value = $input.val().trim();
            const pattern = /^-?[\d.]+\s*(px|em|%|rem|vh|vw|pt|cm|mm)?$/;

            if (!pattern.test(value)) {
                $input.addClass('is-invalid');
                this.showError('Invalid dimension value: ' + value);
            } else {
                $input.removeClass('is-invalid');
            }
        },

        /**
         * Updates the hidden dimension value when input or unit changes
         */
        updateDimensionValue: function($element) {
            const fieldName = $element.data('field-name');
            if (!fieldName) {
                return;
            }

            // Find the related inputs (numeric input and unit select)
            const $parent = $element.closest('div[style*="grid"]');
            if (!$parent.length) {
                return;
            }

            const $numberInput = $parent.find('input[type="text"]:not([type="hidden"])');
            const $unitSelect = $parent.find('.griffinforms-dimension-unit');
            const $hiddenValue = $parent.find('.griffinforms-dimension-value');

            if (!$numberInput.length || !$unitSelect.length || !$hiddenValue.length) {
                return;
            }

            // Get values
            const numericValue = $numberInput.val().trim();
            const unit = $unitSelect.val();

            // Update hidden input with combined value
            const fullValue = numericValue + unit;
            $hiddenValue.val(fullValue);
        },

        /**
         * Checks if color value is valid (hex, rgb, rgba, or named)
         */
        isValidColor: function(color) {
            const hexPattern = /^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/;
            const rgbPattern = /^rgba?\s*\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}(\s*,\s*[\d.]+)?\s*\)$/i;
            const namedPattern = /^[a-z]+$/i;

            return hexPattern.test(color) || rgbPattern.test(color) || namedPattern.test(color);
        },

        /**
         * Normalizes color to hex format (for HTML5 color input)
         */
        normalizeColorToHex: function(color) {
            color = color.trim();

            // Already hex
            if (/^#[0-9a-fA-F]{6}$/.test(color)) {
                return color;
            }

            // RGB to hex
            const rgbMatch = color.match(/^rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i);
            if (rgbMatch) {
                return '#' + [parseInt(rgbMatch[1], 10), parseInt(rgbMatch[2], 10), parseInt(rgbMatch[3], 10)]
                    .map(x => {
                        const hex = x.toString(16);
                        return hex.length === 1 ? '0' + hex : hex;
                    }).join('');
            }

            return '#000000';
        },

        /**
         * Collects all theme data from form inputs
         * Returns nested object structure matching database schema
         */
        collectThemeData: function() {
            const formData = new FormData($('form')[0]);
            const themeData = {};

            // Convert FormData to nested object
            for (const [key, value] of formData.entries()) {
                this.setNestedValue(themeData, key, value);
            }

            // Post-process to add "deg" suffix to gradient angle values
            this.formatGradientAngles(themeData);

            return themeData;
        },

        /**
         * Formats gradient angle values by adding "deg" suffix
         * Converts "45" to "45deg" for CSS generation
         */
        formatGradientAngles: function(themeData) {
            // Process form styles
            if (themeData.form_style) {
                this.addAngleSuffixToStyle(themeData.form_style);
            }

            // Process page styles
            if (themeData.page_style) {
                this.addAngleSuffixToStyle(themeData.page_style);
            }

            // Process button styles
            if (themeData.submit_button || themeData.previous_button || themeData.next_button) {
                if (themeData.submit_button) this.addAngleSuffixToStyle(themeData.submit_button);
                if (themeData.previous_button) this.addAngleSuffixToStyle(themeData.previous_button);
                if (themeData.next_button) this.addAngleSuffixToStyle(themeData.next_button);
            }
        },

        /**
         * Adds "deg" suffix to gradient_angle values in a style object.
         */
        addAngleSuffixToStyle: function(styleObj) {
            if (typeof styleObj !== 'object' || styleObj === null) {
                return;
            }

            Object.keys(styleObj).forEach((key) => {
                const value = styleObj[key];
                if (typeof value !== 'object' || value === null) {
                    return;
                }

                if (Object.prototype.hasOwnProperty.call(value, 'gradient_angle')) {
                    const angle = value.gradient_angle.toString().trim();
                    if (angle && !angle.endsWith('deg')) {
                        value.gradient_angle = angle + 'deg';
                    }
                    return;
                }

                this.addAngleSuffixToStyle(value);
            });
        },

        /**
         * Sets value in nested object using bracket notation
         * e.g., "form_style[default][padding][top]" -> themeData.form_style.default.padding.top
         * Supports unlimited nesting levels
         */
        setNestedValue: function(obj, path, value) {
            // Parse bracket notation to extract all keys at any nesting level
            // Matches: fieldname[key1][key2][key3]... etc
            const parts = [];

            // First, extract the base field name
            const baseMatch = path.match(/^(\w+)/);
            if (!baseMatch) return;

            parts.push(baseMatch[1]);

            // Then extract all bracketed keys
            const bracketRegex = /\[([^\]]+)\]/g;
            let match;
            while ((match = bracketRegex.exec(path)) !== null) {
                parts.push(match[1]);
            }

            if (parts.length === 0) return;

            let current = obj;

            // Build nested structure, setting value at the last key
            for (let i = 0; i < parts.length; i++) {
                const key = parts[i];

                if (i === parts.length - 1) {
                    // Last key - set value
                    current[key] = value;
                } else {
                    // Intermediate keys - create objects if they don't exist
                    if (!(key in current)) {
                        current[key] = {};
                    }
                    current = current[key];
                }
            }
        },

        /**
         * Generates CSS from theme JSON data
         * Used for preview modal and form submission
         */
        generateCssFromTheme: function(themeData) {
            let css = '';

            // Form styles
            if (themeData.form_style) {
                css += this.generateElementCSS('.griffinforms-form-container', themeData.form_style);
            }

            // Page styles
            if (themeData.page_style) {
                css += this.generateElementCSS('.griffinforms-page-container', themeData.page_style);
            }

            // Row styles
            if (themeData.row_style) {
                css += this.generateElementCSS('.griffinforms-form-row', themeData.row_style);
            }

            // Field styles
            if (themeData.field_style) {
                css += this.generateFieldTypeCSS(themeData.field_style);
            }

            // Button styles
            if (themeData.button_style) {
                css += this.generateElementCSS('.griffinforms-button', themeData.button_style);
            }

            return css;
        },

        /**
         * Generates CSS for a specific element with states
         */
        generateElementCSS: function(selector, styleData) {
            let css = '';

            if (!styleData || typeof styleData !== 'object') return css;

            // Handle each state (default, focus, hover)
            for (const state in styleData) {
                if (styleData.hasOwnProperty(state) && typeof styleData[state] === 'object') {
                    const stateSelector = state === 'default' ? selector : selector + ':' + state;
                    css += stateSelector + ' { ' + this.flattenStyleObject(styleData[state]) + ' }\n';
                }
            }

            return css;
        },

        /**
         * Generates CSS for field types with their respective selectors
         */
        generateFieldTypeCSS: function(fieldStyleData) {
            let css = '';

            if (!fieldStyleData || typeof fieldStyleData !== 'object') return css;

            for (const fieldType in fieldStyleData) {
                if (fieldStyleData.hasOwnProperty(fieldType)) {
                    const selector = this.getFieldTypeSelector(fieldType);
                    const states = fieldStyleData[fieldType];

                    for (const state in states) {
                        if (states.hasOwnProperty(state) && typeof states[state] === 'object') {
                            const stateSelector = state === 'default' ? selector : selector + ':' + state;
                            css += stateSelector + ' { ' + this.flattenStyleObject(states[state]) + ' }\n';
                        }
                    }
                }
            }

            return css;
        },

        /**
         * Gets CSS selector for field type
         */
        getFieldTypeSelector: function(fieldType) {
            const selectors = {
                'text_input': 'input[type="text"], input[type="email"], input[type="number"], input[type="url"], input[type="tel"], input[type="password"], input[type="date"], input[type="time"]',
                'textarea': 'textarea',
                'select_input': 'select',
                'checkbox_radio': 'input[type="checkbox"], input[type="radio"]',
                'file_upload': 'input[type="file"]',
                'address': '.griffinforms-address-field'
            };

            return selectors[fieldType] || '.griffinforms-field';
        },

        /**
         * Flattens nested style object to CSS declarations
         */
        flattenStyleObject: function(styleObj) {
            let css = '';
            let customCss = '';

            // First pass: handle background property specially to combine gradient/image with background_color
            let backgroundObj = {};
            for (const prop in styleObj) {
                if (styleObj.hasOwnProperty(prop)) {
                    if (prop === 'background_color' || prop === 'background_mode' ||
                        prop.startsWith('gradient_') || prop.startsWith('background_image')) {
                        backgroundObj[prop] = styleObj[prop];
                    }
                }
            }

            // If we have any background-related properties, handle them together
            if (Object.keys(backgroundObj).length > 0) {
                css += this.handleComplexProperty('background', backgroundObj);
            }

            // Second pass: handle all other properties (except custom_css which is processed at the end)
            for (const prop in styleObj) {
                if (styleObj.hasOwnProperty(prop) &&
                    prop !== 'background_color' &&
                    prop !== 'background_mode' &&
                    !prop.startsWith('gradient_') &&
                    !prop.startsWith('background_image') &&
                    prop !== 'custom_css') {
                    const cssProp = this.convertToCssProp(prop);
                    const value = styleObj[prop];

                    if (typeof value === 'object') {
                        css += this.handleComplexProperty(cssProp, value);
                    } else {
                        css += cssProp + ': ' + value + '; ';
                    }
                }
            }

            // Third pass: append custom CSS at the end so it overrides UI-generated properties
            if (styleObj.custom_css && styleObj.custom_css.trim()) {
                customCss = styleObj.custom_css;
                // Ensure custom CSS ends with semicolon if it has content
                if (customCss && !customCss.trim().endsWith(';')) {
                    customCss = customCss.trim() + '; ';
                }
                // Add space before custom CSS if main CSS exists
                if (css && customCss) {
                    css += ' ';
                }
                css += customCss;
            }

            return css;
        },

        /**
         * Converts JavaScript property name to CSS property name
         * e.g., background_color -> background-color
         */
        convertToCssProp: function(prop) {
            return prop.replace(/_/g, '-').toLowerCase();
        },

        /**
         * Handles complex CSS properties with multiple values (border, box-shadow, gradient, etc.)
         */
        handleComplexProperty: function(prop, value) {
            let css = '';

            if (prop === 'border') {
                if (value.color) css += 'border-color: ' + value.color + '; ';
                if (value.style) css += 'border-style: ' + value.style + '; ';
                if (value.width) {
                    css += 'border-width: ' + this.formatSides(value.width) + '; ';
                }
            } else if (prop === 'box-shadow') {
                const offsetX = value.offset_x || '0px';
                const offsetY = value.offset_y || '0px';
                const blur = value.blur || '0px';
                const spread = value.spread || '0px';
                const color = value.color || 'rgba(0,0,0,0)';
                css += prop + ': ' + offsetX + ' ' + offsetY + ' ' + blur + ' ' + spread + ' ' + color + '; ';
            } else if (prop === 'background') {
                // Handle background based on mode: single, gradient, or image
                const mode = value.background_mode || 'single';

                if (mode === 'gradient' && value.gradient_color_1 && value.gradient_color_2) {
                    // Gradient mode
                    const angle = value.gradient_angle || '45deg';
                    const color1 = value.gradient_color_1;
                    const color2 = value.gradient_color_2;
                    css += prop + ': linear-gradient(' + angle + ', ' + color1 + ', ' + color2 + '); ';
                } else if (mode === 'image' && value.background_image) {
                    // Image mode
                    const imageUrl = value.background_image;
                    const size = value.background_image_size || 'cover';
                    const position = value.background_image_position || 'center';
                    const repeat = value.background_image_repeat || 'no-repeat';

                    css += 'background-image: url("' + imageUrl + '"); ';
                    css += 'background-size: ' + size + '; ';
                    css += 'background-position: ' + position + '; ';
                    css += 'background-repeat: ' + repeat + '; ';
                } else if (value.background_color) {
                    // Single color mode (default)
                    css += prop + ': ' + value.background_color + '; ';
                }
            } else if (prop === 'padding' || prop === 'margin') {
                css += prop + ': ' + this.formatSides(value) + '; ';
            }

            return css;
        },

        /**
         * Formats 4-sided values (padding, margin) from object to CSS string
         */
        formatSides: function(sideObj) {
            if (typeof sideObj === 'object' && sideObj !== null) {
                return (sideObj.top || '0') + ' ' + (sideObj.right || '0') + ' ' +
                       (sideObj.bottom || '0') + ' ' + (sideObj.left || '0');
            }
            return sideObj;
        },

        /**
         * Saves theme to database
         */
        saveTheme: function() {
            const self = this;
            const $form = $('form');

            // Validate required fields
            if (!this.validateForm()) {
                this.showError('Please fill in all required fields');
                return;
            }

            // Collect data
            const themeData = this.collectThemeData();

            // Determine if create or update
            const itemId = $('[name="item_id"]').val();
            const action = itemId ? 'updateItem' : 'createItem';

            // Get nonce from form
            const nonce = $('[name="mg_nonce"]').val() || '';

            // AJAX request
            $.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: action,
                    item_type: 'formtheme',
                    item_data: JSON.stringify(themeData),
                    nonce: nonce,
                    item_id: itemId
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showSuccess('Theme saved successfully');
                        setTimeout(function() {
                            window.location.href = ajaxurl.replace('admin-ajax.php', 'admin.php?page=griffinforms-formthemes');
                        }, 1500);
                    } else {
                        self.showError(response.message || 'Failed to save theme');
                    }
                },
                error: function() {
                    self.showError('An error occurred while saving the theme');
                }
            });
        },

        /**
         * Validates form inputs
         */
        validateForm: function() {
            const $name = $('[name="name"]');
            if (!$name.val() || $name.val().trim() === '') {
                $name.addClass('is-invalid');
                return false;
            }
            $name.removeClass('is-invalid');
            return true;
        },

        /**
         * Shows error message
         */
        showError: function(message) {
            // Create alert if doesn't exist
            if ($('#griffinforms-theme-error').length === 0) {
                $('form').before('<div id="griffinforms-theme-error" class="alert alert-danger alert-dismissible fade show" role="alert"><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
            }

            $('#griffinforms-theme-error').html(message).show();

            // Auto-dismiss after 5 seconds
            setTimeout(function() {
                $('#griffinforms-theme-error').fadeOut();
            }, 5000);
        },

        /**
         * Shows success message
         */
        showSuccess: function(message) {
            // Create alert if doesn't exist
            if ($('#griffinforms-theme-success').length === 0) {
                $('form').before('<div id="griffinforms-theme-success" class="alert alert-success alert-dismissible fade show" role="alert"><button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
            }

            $('#griffinforms-theme-success').html(message).show();

            // Auto-dismiss after 5 seconds
            setTimeout(function() {
                $('#griffinforms-theme-success').fadeOut();
            }, 5000);
        },

        /**
         * Copies button styles from source button to target button
         * Copies all field values across all states (default, focus, hover)
         */
        copyButtonStyles: function(sourceButton, targetButton) {
            const sourceSelector = '.griffinforms-button-' + sourceButton;
            const targetSelector = '.griffinforms-button-' + targetButton;

            // Find all input fields in source button section
            const $sourceFields = $(sourceSelector).find('input, select, textarea');

            if ($sourceFields.length === 0) {
                alert('No source fields found');
                return;
            }

            // For each source field, find corresponding target field and copy value
            $sourceFields.each(function() {
                const $sourceField = $(this);
                const fieldName = $sourceField.attr('name');

                if (!fieldName) return;

                // Replace source button name with target button name in the field name
                const targetFieldName = fieldName.replace(sourceButton + '_button', targetButton + '_button');

                // Find target field with the new name
                const $targetField = $('input[name="' + targetFieldName + '"], select[name="' + targetFieldName + '"], textarea[name="' + targetFieldName + '"]');

                if ($targetField.length) {
                    // Copy the value
                    $targetField.val($sourceField.val());

                    // Trigger change event to update dependent fields
                    $targetField.trigger('change');
                }
            });

            // Show success message
            const buttonLabels = {
                'submit': 'Submit Button',
                'previous': 'Previous Button',
                'next': 'Next Button'
            };

            const message = 'Copied all styles from ' + buttonLabels[sourceButton] + ' to ' + buttonLabels[targetButton];
            this.showSuccess(message);
        }
    };

    // Initialize when document is ready
    $(document).ready(function() {
        GriffinFormsTheme.init();
    });

})(jQuery);
