/**
 * VMPFence Onboarding Tour Engine
 *
 * Displays guided tours with overlay cards positioned
 * relative to target UI sections on plugin pages.
 *
 * @package VMPFence
 * @since 2.2.4
 */

(function($) {
    'use strict';

    // Tour state
    let currentStep = 0;
    let tourSteps = [];
    let currentStepData = null;
    let pageKey = '';
    let backdropElement = null;
    let cardElement = null;
    let arrowElement = null;
    let currentTarget = null;
    let currentPlacement = 'bottom';

    // Constants
    const GAP = 20;        // Space between card and target (px)
    const ARROW_SIZE = 18; // Arrow CSS border-width (px)

    /**
     * Initialize the onboarding tour
     */
    function initTour() {
        // Check if tour data is available
        if (typeof vmpfenceOnboarding === 'undefined' || !vmpfenceOnboarding.steps || vmpfenceOnboarding.steps.length === 0) {
            return;
        }

        tourSteps = vmpfenceOnboarding.steps;
        pageKey = vmpfenceOnboarding.pageKey;

        // Create backdrop
        createBackdrop();

        // Show first step
        showStep(0);
    }

    /**
     * Create the backdrop overlay scoped to #wpcontent
     */
    function createBackdrop() {
        backdropElement = $('<div>', {
            class: 'vmpfence-onboarding-backdrop'
        });

        // Backdrop clicks do NOT dismiss tour - only X button or Got it button can close it
        positionBackdrop();
        $('body').append(backdropElement);
    }

    /**
     * Position backdrop to cover only the plugin content area
     * (excludes WP admin bar and sidebar)
     */
    function positionBackdrop() {
        if (!backdropElement) return;
        var $wpcontent = $('#wpcontent');
        var $adminBar  = $('#wpadminbar');
        var topOffset  = $adminBar.length ? $adminBar.outerHeight() : 32;
        var leftOffset = $wpcontent.length ? $wpcontent.offset().left : 0;

        backdropElement.css({
            top:    topOffset + 'px',
            left:   leftOffset + 'px',
            right:  '0',
            bottom: '0'
        });
    }

    /**
     * Show a specific tour step
     *
     * @param {number} index Step index
     */
    function showStep(index) {
        if (index < 0 || index >= tourSteps.length) {
            return;
        }

        currentStep = index;
        const step = tourSteps[index];

        // Find target element
        const $target = $(step.selector);

        // If target doesn't exist, skip to next step
        if ($target.length === 0) {
            console.warn('VMPFence Onboarding: Target element not found:', step.selector);
            
            // Try next step
            if (index + 1 < tourSteps.length) {
                showStep(index + 1);
            } else {
                // No more steps, dismiss tour
                dismissTour();
            }
            return;
        }

        // Remove highlight from previous target
        if (currentTarget) {
            // No highlight needed - arrow will point to target
        }

        // Set new target
        currentTarget = $target.first();

        // Store current step data for positioning
        currentStepData = step;

        // Check if target is in a tab content area and switch tab if needed
        const $tabContent = currentTarget.closest('.vmpfence-tab-content');
        if ($tabContent.length > 0 && !$tabContent.hasClass('active')) {
            // Find the tab ID
            const tabId = $tabContent.attr('id');
            if (tabId) {
                // Click the corresponding tab button
                const $tabButton = $('.vmpfence-tabs-nav button[data-tab="' + tabId + '"]');
                if ($tabButton.length > 0) {
                    $tabButton.trigger('click');
                    
                    // Wait for tab transition
                    setTimeout(function() {
                        proceedWithStep(step);
                    }, 300);
                    return;
                }
            }
        }

        proceedWithStep(step);
    }

    /**
     * Proceed with showing the step after any tab switching
     */
    function proceedWithStep(step) {
        // No highlight class added

        // Create or update card
        if (cardElement) {
            updateCard(step);
        } else {
            createCard(step);
        }

        // Position the card relative to the target, then scroll to show both
        setTimeout(function() {
            positionCard();
            scrollToShowTargetAndModal();
        }, 100);
    }

    /**
     * Scroll to show both target element and modal in viewport
     */
    function scrollToShowTargetAndModal() {
        if (!currentTarget || !cardElement) return;

        var targetTop    = currentTarget.offset().top;
        var targetBottom = targetTop + currentTarget.outerHeight();
        var cardTop      = cardElement.offset().top;
        var cardBottom   = cardTop + cardElement.outerHeight();

        // Bounding box that encloses both elements (handles all placements)
        var contentTop    = Math.min(targetTop, cardTop);
        var contentBottom = Math.max(targetBottom, cardBottom);
        var contentHeight = contentBottom - contentTop;

        var windowHeight = $(window).height();
        var scrollTop    = $(window).scrollTop();
        var padding      = 40;
        var targetScroll;

        if (contentHeight + (padding * 2) <= windowHeight) {
            // Both fit in viewport — centre them
            targetScroll = contentTop - (windowHeight - contentHeight) / 2;
        } else {
            // Too tall — align whichever is higher to top with padding
            targetScroll = contentTop - padding;
        }

        targetScroll = Math.max(0, targetScroll);

        var vpTop    = scrollTop;
        var vpBottom = scrollTop + windowHeight;

        if (contentTop < vpTop + padding || contentBottom > vpBottom - padding) {
            $('html, body').animate({ scrollTop: targetScroll }, 400);
        }
    }

    /**
     * Create the onboarding card
     *
     * @param {Object} step Step data
     */
    function createCard(step) {
        // Create card structure
        cardElement = $('<div>', {
            class: 'vmpfence-onboarding-card'
        });

        const header = $('<div>', {
            class: 'vmpfence-onboarding-header'
        });

        // Close button
        const closeBtn = $('<button>', {
            class: 'vmpfence-onboarding-close',
            'aria-label': 'Close tour',
            html: '&times;'
        });

        closeBtn.on('click', function(e) {
            e.preventDefault();
            dismissTour();
        });

        // Title
        const title = $('<h3>', {
            class: 'vmpfence-onboarding-title',
            text: step.title
        });

        header.append(closeBtn, title);

        // Icon (if provided) - appears below title
        if (step.iconSvg) {
            // Custom SVG icon
            const icon = $('<div>', {
                class: 'vmpfence-onboarding-icon vmpfence-onboarding-icon-svg',
                html: step.iconSvg
            });
            header.append(icon);
        } else if (step.icon) {
            // Dashicon
            const icon = $('<span>', {
                class: 'vmpfence-onboarding-icon dashicons ' + step.icon
            });
            header.append(icon);
        }

        // Body
        const body = $('<div>', {
            class: 'vmpfence-onboarding-body'
        });

        const description = $('<p>', {
            class: 'vmpfence-onboarding-desc',
            html: step.description
        });

        body.append(description);

        // Footer
        const footer = createFooter();

        // Assemble card
        cardElement.append(header, body, footer);

        // Add to body
        $('body').append(cardElement);

        // Create arrow element
        createArrow();
    }

    /**
     * Update existing card content
     *
     * @param {Object} step Step data
     */
    function updateCard(step) {
        // Update icon
        const $icon = cardElement.find('.vmpfence-onboarding-icon');
        if (step.iconSvg) {
            // Custom SVG icon
            if ($icon.length > 0 && $icon.hasClass('vmpfence-onboarding-icon-svg')) {
                $icon.html(step.iconSvg);
            } else {
                $icon.remove();
                const icon = $('<div>', {
                    class: 'vmpfence-onboarding-icon vmpfence-onboarding-icon-svg',
                    html: step.iconSvg
                });
                cardElement.find('.vmpfence-onboarding-header').append(icon);
            }
        } else if (step.icon) {
            // Dashicon
            if ($icon.length > 0 && !$icon.hasClass('vmpfence-onboarding-icon-svg')) {
                $icon.attr('class', 'vmpfence-onboarding-icon dashicons ' + step.icon);
            } else {
                $icon.remove();
                const icon = $('<span>', {
                    class: 'vmpfence-onboarding-icon dashicons ' + step.icon
                });
                cardElement.find('.vmpfence-onboarding-header').append(icon);
            }
        } else {
            $icon.remove();
        }

        // Update title
        cardElement.find('.vmpfence-onboarding-title').text(step.title);

        // Update description with HTML support
        cardElement.find('.vmpfence-onboarding-desc').html(step.description);

        // Update footer (dots and button)
        cardElement.find('.vmpfence-onboarding-footer').replaceWith(createFooter());

        // Recreate arrow (direction resolved in positionCard → updateArrow)
        if (arrowElement) {
            arrowElement.remove();
        }
        createArrow();
    }

    /**
     * Create the card footer with dots and button
     *
     * @return {jQuery} Footer element
     */
    function createFooter() {
        const footer = $('<div>', {
            class: 'vmpfence-onboarding-footer'
        });

        const isFirstStep = currentStep === 0;
        const isLastStep = currentStep === tourSteps.length - 1;

        // Previous button (only show if not first step)
        let prevButton = null;
        if (!isFirstStep) {
            prevButton = $('<button>', {
                class: 'vmpfence-onboarding-btn vmpfence-onboarding-btn-prev',
                text: 'PREVIOUS'
            });

            prevButton.on('click', function(e) {
                e.preventDefault();
                if (currentStep > 0) {
                    showStep(currentStep - 1);
                }
            });
        }

        // Progress dots
        const dots = $('<div>', {
            class: 'vmpfence-onboarding-dots'
        });

        for (let i = 0; i < tourSteps.length; i++) {
            const dot = $('<span>', {
                class: 'vmpfence-onboarding-dot' + (i === currentStep ? ' active' : '')
            });
            dots.append(dot);
        }

        // Next/Got it button
        const nextButton = $('<button>', {
            class: 'vmpfence-onboarding-btn ' + (isLastStep ? 'vmpfence-onboarding-btn-gotit' : 'vmpfence-onboarding-btn-next'),
            text: isLastStep ? 'GOT IT' : 'NEXT'
        });

        nextButton.on('click', function(e) {
            e.preventDefault();
            if (isLastStep) {
                dismissTour();
            } else {
                nextStep();
            }
        });

        // Append elements (conditionally append previous button)
        if (prevButton) {
            footer.append(prevButton);
        }
        footer.append(dots, nextButton);

        return footer;
    }

    /**
     * Determine best placement for the card relative to its target.
     *
     * Checks available space in each direction and returns the first
     * direction where both card and target fit in one viewport.
     * Preference order: bottom → top → right → left.
     *
     * @param {jQuery} target  Target element
     * @param {jQuery} card    Card element (must be in DOM for measurement)
     * @return {string} 'bottom'|'top'|'right'|'left'
     */
    function determinePlacement(target, card) {
        var viewportH   = $(window).height();
        var viewportW   = $(window).width();
        var adminBarH   = $('#wpadminbar').outerHeight() || 32;

        var targetOff   = target.offset();
        var targetH     = target.outerHeight();
        var targetW     = target.outerWidth();
        var cardW       = card.outerWidth();
        var cardH       = card.outerHeight();

        var $wpc        = $('#wpcontent');
        var contentLeft = $wpc.length ? $wpc.offset().left : 0;
        var contentW    = $wpc.length ? $wpc.outerWidth()  : viewportW;

        // Vertical: can target + gap + card fit inside one viewport?
        var viewable = viewportH - adminBarH - 40; // 40 = breathing room
        var totalV   = targetH + GAP + cardH;

        if (totalV <= viewable) return 'bottom';

        // Target is tall — try above if enough document space
        if (targetOff.top - adminBarH >= cardH + GAP) return 'top';

        // Horizontal options
        var fitsRight = (targetOff.left + targetW + GAP + cardW) <= (contentLeft + contentW - 10);
        var fitsLeft  = (targetOff.left - GAP - cardW) >= (contentLeft + 10);

        if (fitsRight) return 'right';
        if (fitsLeft)  return 'left';

        // Nothing ideal — fall back to bottom & scroll
        return 'bottom';
    }

    /**
     * Position the card relative to the target element.
     *
     * Uses determinePlacement() unless the step explicitly sets `placement`.
     * The card is centred on the target's axis for the chosen direction,
     * then clamped within the visible content area.
     */
    function positionCard() {
        if (!cardElement || !currentTarget) return;

        var step = currentStepData;

        // Resolve placement: explicit per-step override or auto-detect
        var placement = (step && step.placement)
            ? step.placement
            : determinePlacement(currentTarget, cardElement);
        currentPlacement = placement;

        var targetOff = currentTarget.offset();
        var targetW   = currentTarget.outerWidth();
        var targetH   = currentTarget.outerHeight();
        var cardW     = cardElement.outerWidth();
        var cardH     = cardElement.outerHeight();

        var $wpc        = $('#wpcontent');
        var contentLeft = $wpc.length ? $wpc.offset().left : 0;
        var contentW    = $wpc.length ? $wpc.outerWidth()  : $(window).width();
        var adminBarH   = $('#wpadminbar').outerHeight() || 32;

        var top, left;

        switch (placement) {
            case 'top':
                top  = targetOff.top - GAP - cardH;
                left = targetOff.left + (targetW / 2) - (cardW / 2);
                break;
            case 'right':
                top  = targetOff.top + (targetH / 2) - (cardH / 2);
                left = targetOff.left + targetW + GAP;
                break;
            case 'left':
                top  = targetOff.top + (targetH / 2) - (cardH / 2);
                left = targetOff.left - GAP - cardW;
                break;
            case 'bottom':
            default:
                top  = targetOff.top + targetH + GAP;
                left = targetOff.left + (targetW / 2) - (cardW / 2);
                break;
        }

        // Optional manual nudge (percentage of target dimensions)
        // offsetTop: percentage of target height, offsetLeft: percentage of target width
        if (step && step.offsetTop)  top  += targetH * (parseFloat(step.offsetTop) / 100);
        if (step && step.offsetLeft) left += targetW * (parseFloat(step.offsetLeft) / 100);

        // Clamp horizontal bounds within content area
        var margin  = 20;
        var minLeft = contentLeft + margin;
        var maxLeft = contentLeft + contentW - cardW - margin;
        left = Math.max(minLeft, Math.min(left, maxLeft));

        // Don't overlap admin bar
        top = Math.max(adminBarH + 10, top);

        cardElement.css({
            top:       top + 'px',
            left:      left + 'px',
            transform: 'none'
        });

        // Update arrow direction & position for resolved placement
        updateArrow();
    }

    /**
     * Create the arrow element (direction set later by updateArrow)
     */
    function createArrow() {
        arrowElement = $('<div>', { class: 'vmpfence-onboarding-arrow' });
        cardElement.append(arrowElement);
    }

    /**
     * Update arrow direction and position based on currentPlacement.
     *
     * Placement-to-arrow map:
     *   bottom → arrow-up    (arrow at card top,    pointing up)
     *   top    → arrow-down  (arrow at card bottom, pointing down)
     *   right  → arrow-left  (arrow at card left,   pointing left)
     *   left   → arrow-right (arrow at card right,  pointing right)
     */
    function updateArrow() {
        if (!arrowElement || !cardElement || !currentTarget) return;

        var arrowMap = {
            'bottom': 'up',
            'top':    'down',
            'right':  'left',
            'left':   'right'
        };

        // Per-step arrow override takes priority over auto-derived direction
        var direction = (currentStepData && currentStepData.arrow)
            ? currentStepData.arrow
            : (arrowMap[currentPlacement] || 'up');
        arrowElement.attr('class', 'vmpfence-onboarding-arrow arrow-' + direction);

        // Reset inline styles so CSS defaults apply first
        arrowElement.css({ left: '', right: '', top: '', bottom: '', transform: '' });

        var targetOff = currentTarget.offset();
        var targetW   = currentTarget.outerWidth();
        var targetH   = currentTarget.outerHeight();
        var cardOff   = cardElement.offset();
        var cardW     = cardElement.outerWidth();
        var cardH     = cardElement.outerHeight();
        var margin    = 30;

        if (direction === 'up' || direction === 'down') {
            // Position horizontally to point at target's centre
            var targetCX  = targetOff.left + (targetW / 2);
            var arrowLeft = targetCX - cardOff.left - ARROW_SIZE;

            // Optional per-step fine-tuning
            if (currentStepData && currentStepData.arrowOffsetX) {
                arrowLeft += currentStepData.arrowOffsetX;
            }

            // Clamp within card edges
            arrowLeft = Math.max(margin, Math.min(arrowLeft, cardW - margin - ARROW_SIZE * 2));
            arrowElement.css({ left: arrowLeft + 'px' });

        } else {
            // Position vertically to point at target's centre
            var targetCY = targetOff.top + (targetH / 2);
            var arrowTop = targetCY - cardOff.top - ARROW_SIZE;

            // Clamp within card edges
            arrowTop = Math.max(margin, Math.min(arrowTop, cardH - margin - ARROW_SIZE * 2));
            arrowElement.css({ top: arrowTop + 'px', transform: 'none' });
        }
    }

    /**
     * Move to next step
     */
    function nextStep() {
        if (currentStep < tourSteps.length - 1) {
            showStep(currentStep + 1);
        }
    }

    /**
     * Dismiss the tour permanently
     */
    function dismissTour() {
        // Remove highlight (not used, but keep for compatibility)
        if (currentTarget) {
            // No highlight to remove
        }

        // Remove arrow
        if (arrowElement) {
            arrowElement.fadeOut(200, function() {
                arrowElement.remove();
                arrowElement = null;
            });
        }

        // Remove card
        if (cardElement) {
            cardElement.fadeOut(200, function() {
                cardElement.remove();
                cardElement = null;
            });
        }

        // Remove backdrop
        if (backdropElement) {
            backdropElement.fadeOut(200, function() {
                backdropElement.remove();
                backdropElement = null;
            });
        }

        // Send AJAX request to mark tour as dismissed
        $.ajax({
            url: vmpfenceOnboarding.ajaxUrl,
            type: 'POST',
            data: {
                action: 'vmpfence_dismiss_onboarding',
                nonce: vmpfenceOnboarding.nonce,
                page_key: pageKey
            },
            success: function(response) {
                if (!response.success) {
                    console.error('VMPFence Onboarding: Failed to dismiss tour', response);
                }
            },
            error: function(xhr, status, error) {
                console.error('VMPFence Onboarding: AJAX error', error);
            }
        });
    }

    /**
     * Handle window resize
     */
    function handleResize() {
        positionBackdrop();
        if (cardElement && currentTarget) {
            positionCard();
        }
    }

    // Debounce helper
    function debounce(func, wait) {
        let timeout;
        return function() {
            const context = this;
            const args = arguments;
            clearTimeout(timeout);
            timeout = setTimeout(function() {
                func.apply(context, args);
            }, wait);
        };
    }

    // Initialize tour when DOM is ready
    $(document).ready(function() {
        // Wait a bit for the page to fully render
        setTimeout(initTour, 500);

        // Handle window resize
        $(window).on('resize', debounce(handleResize, 250));

        // Escape key disabled - only X button or Got it button can close tour
    });

})(jQuery);
