document.addEventListener('DOMContentLoaded', function () {
    setTimeout(tp_InitGsapTimeline, 500);
});

function tp_canAccessTimeline() {
    return typeof tp_ajax_obj !== 'undefined' &&
        tp_ajax_obj &&
        tp_ajax_obj.is_logged_in === 'yes' &&
        tp_ajax_obj.can_access_timeline === 'yes';
}

function tp_InitGsapTimeline() {

    var container = document.querySelector('.tp-vis-timeline');
    let iframe = document.getElementById('elementor-preview-iframe');
    let scopeDoc = document;
    let scopeWin = window;

    if (iframe && iframe.contentDocument) {
        scopeDoc = iframe.contentDocument;
        scopeWin = iframe.contentWindow;
        if (!container) {
            container = scopeDoc.querySelector('.tp-vis-timeline');
        }
    }

    if (!container) {
        return;
    }

    if (!tp_canAccessTimeline()) {
        container.remove();
        return;
    }

    let isEditor = typeof window.elementor !== 'undefined' || typeof parent.elementor !== 'undefined';
    let postId = (window.elementorConfig ? window.elementorConfig.post_id : null) ||
        (window.elementor && window.elementor.config && window.elementor.config.document ? window.elementor.config.document.id : null) ||
        new URLSearchParams(window.location.search).get('post');

    tp_injectModalHTML();
    tp_setupModalButtons(isEditor);

    if (isEditor) {
        let editorPostId = postId || (parent.elementor && parent.elementor.config && parent.elementor.config.document ? parent.elementor.config.document.id : null);
        if (!editorPostId) {
            return;
        }
        jQuery.ajax({
            url: tp_ajax_obj.ajax_url,
            type: 'POST',
            dataType: 'json',
            data: {
                action: 'tp_get_gsap_timeline_data',
                post_id: editorPostId,
                security: tp_ajax_obj.nonce
            },
            success: function (res) {
                if (res.success) {
                    tp_processTimelineData(res.data, container, scopeWin, scopeDoc, isEditor, postId);
                }
            }
        });

        if (!window.tpTimelineInited) {
            window.tpTimelineInited = true;
            window.elementor.on('preview:loaded', function () {
                setTimeout(tp_InitGsapTimeline, 1000);
            });
        }
    } else {

        // Frontend: Use DOM querySelector
        var magic_scroll = scopeDoc.querySelectorAll('.tp-magic-scroll');
        if (!magic_scroll.length) return;

        let frontendData = [];
        magic_scroll.forEach(function (self) {
            if (!self.dataset.tpmsMs) return;
            try {
                let msData = JSON.parse(self.dataset.tpmsMs);
                if (!msData[0] || !msData[0].advanced_timeline) return;
                frontendData.push({
                    widgetId: self.dataset.tpWidgetId,
                    postId: self.dataset.tpPostId,
                    settings: msData[0],
                    name: msData[0].develop_name || `Widget`
                });
            } catch (e) { }
        });
        tp_processTimelineData(frontendData, container, scopeWin, scopeDoc, isEditor, postId);
    }
}

function tp_processTimelineData(list, container, scopeWin, scopeDoc, isEditor, postId) {

    if (!list || !list.length) return;


    tp_injectTimelineControls(container);

    let itemsArray = [];
    let groupsArray = [];
    let idCounter = 1;
    let viewportHeight = scopeWin.innerHeight;

    list.forEach(function (item) {


        let widgetId = item.widgetId;
        let currentPostId = item.postId || postId;
        let settings = item.settings;
        if (!settings) return;
        if (isEditor && settings.advanced_gsapTimeline !== 'yes') return;
        if (!isEditor && !settings.advanced_timeline) return;

        let duration = Number(settings.durationtp?.size || settings.duration?.md || 300);
        let offsetVal = Number(settings.offsettp?.size || settings.offset?.md || 0);
        let triggerVal = Number(settings.triggertp?.size || settings.trigger?.md || 0.5);
        let name = '';

        if (isEditor) {
            name = settings.devNametp || `Widget ${idCounter}`;
        } else {
            name = item.name || settings.develop_name || `Widget ${idCounter}`;
        }

        if (!duration) return;

        // Find element in Iframe
        let el = scopeDoc.querySelector(`[data-tp-widget-id="${widgetId}"]`);
        if (!el && isEditor) {
            // Fallback for Elementor Editor: try data-id which is standard for widget wrappers
            el = scopeDoc.querySelector(`.elementor-element[data-id="${widgetId}"]`);
        }
        if (!el) return;



        let rect = el.getBoundingClientRect();
        let elementTopAbsolute = rect.top + scopeWin.scrollY;

        let baseStartPixel = elementTopAbsolute - (viewportHeight * triggerVal);
        let startPixel = baseStartPixel + offsetVal;
        let endPixel = startPixel + duration;

        groupsArray.push({ id: idCounter, content: `<div style="padding-right:10px;">${name}</div>`, value: idCounter });

        itemsArray.push({
            id: idCounter,
            group: idCounter,
            content: tp_getCardHTML(triggerVal, duration, offsetVal),
            start: startPixel,
            end: endPixel,
            type: 'range',
            className: 'tp-vis-item-wrapper',
            meta: {
                widgetId: widgetId,
                postId: currentPostId,
                duration: duration,
                offset: offsetVal,
                trigger: triggerVal,
                baseLine: baseStartPixel
            }
        });
        idCounter++;
    });

    if (!itemsArray.length) return;

    var itemsDataSet = new vis.DataSet(itemsArray);
    var groupsDataSet = new vis.DataSet(groupsArray);
    let totalScroll = scopeDoc.documentElement.scrollHeight - scopeWin.innerHeight;

    let containerWidth = container.clientWidth || 800;
    let visibleRange = (containerWidth / 100) * 50;

    var timelineOptions = {
        start: -200,
        end: -200 + visibleRange,
        min: -2000,
        max: totalScroll + 3000,
        zoomable: true,
        moveable: true,
        zoomMin: 100,
        zoomMax: 10000,
        showCurrentTime: false,
        orientation: 'top',
        stack: false,
        groupHeightMode: 'fixed',
        editable: { add: false, remove: false, updateGroup: false, updateTime: true },
        snap: (date, scale, step) => {
            return Math.round(date / 50) * 50;
        },
        align: 'left',
        showMinorLabels: true,
        showMajorLabels: true,
        timeAxis: {
            scale: 'millisecond',
            step: 50
        },
        format: {
            minorLabels: (date) => Math.round(date) + 'px',
            majorLabels: (date) => ''
        },

        onMoving: function (item, callback) {
            let newDuration = Math.round(item.end - item.start);
            if (newDuration === item.meta.duration) {
                callback(null);
            } else {
                callback(item);
            }
        },

        onMove: function (item, callback) {
            let newEnd = item.end;
            let newStart = item.start;
            let newDuration = Math.round(newEnd - newStart);
            let newOffset = Math.round(newStart - item.meta.baseLine);

            item.meta.duration = newDuration;
            item.meta.offset = newOffset;
            item.content = tp_getCardHTML(item.meta.trigger, newDuration, newOffset);

            tp_AutoSaveToDB(item.meta);
            callback(item);
        }
    };

    // Clear previous timeline instances to avoid duplication in Elementor editor
    const existingTimeline = container.querySelector('.vis-timeline');
    if (existingTimeline) {
        existingTimeline.remove();
    }

    var timeline = new vis.Timeline(container, itemsDataSet, groupsDataSet, timelineOptions);
    container._tpTimeline = timeline;
    tp_refreshTimelineLayout(container);

    timeline.addCustomTime(0, 'scrollIndicator');
    scopeWin.addEventListener('scroll', function () {
        timeline.setCustomTime(scopeWin.scrollY, 'scrollIndicator');
    });

    // --- 5. EVENTS ---
    timeline.on('doubleClick', function (properties) {
        if (!properties.item) return;
        let itemData = itemsDataSet.get(properties.item);
        tp_openEditModal(itemData.meta);
    });

    tp_setupWindowControls(container, scopeWin, scopeDoc);
}

function tp_setupModalButtons(isEditor) {
    const btnSave = document.getElementById('tp-btn-save');
    if (btnSave && !btnSave.hasAttribute('data-tp-bound')) {
        btnSave.setAttribute('data-tp-bound', 'true');
        btnSave.addEventListener('click', function () {
            let currentMeta = tp_getModalMeta();
            if (!currentMeta) return;

            currentMeta.duration = Number(document.getElementById('tp-input-duration').value);
            currentMeta.offset = Number(document.getElementById('tp-input-offset').value);
            currentMeta.trigger = Number(document.getElementById('tp-input-trigger').value);

            btnSave.innerText = 'Saving...';
            tp_AutoSaveToDB(currentMeta, function () {
                btnSave.innerText = 'Done!';
                setTimeout(() => {
                    btnSave.innerText = 'Save';
                    document.getElementById('tp-custom-modal').style.display = 'none';
                    if (isEditor) {
                        elementor.reloadPreview();
                    } else {
                        location.reload();
                    }
                }, 500);
            });
        });
    }

    const btnCancel = document.getElementById('tp-btn-cancel');
    if (btnCancel && !btnCancel.hasAttribute('data-tp-bound')) {
        btnCancel.setAttribute('data-tp-bound', 'true');
        btnCancel.addEventListener('click', () => {
            document.getElementById('tp-custom-modal').style.display = 'none';
        });
    }

    const btnClose = document.getElementById('tp-modal-close');
    if (btnClose && !btnClose.hasAttribute('data-tp-bound')) {
        btnClose.setAttribute('data-tp-bound', 'true');
        btnClose.addEventListener('click', () => {
            document.getElementById('tp-custom-modal').style.display = 'none';
        });
    }

    if (!window.tpModalEscBound) {
        window.tpModalEscBound = true;
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape') {
                const modal = document.getElementById('tp-custom-modal');
                if (modal && modal.style.display !== 'none') {
                    modal.style.display = 'none';
                }
            }
        });
    }
}

function tp_getCardHTML(trigger, duration, offset) {
    return `<div class="tp-timeline-card">
        <div class="tp-card-meta">
            <span class="tp-meta-item"> <i class="theplus-i-target"></i>${trigger}</span>
            <span class="tp-meta-item"> <i class="theplus-i-duration"></i>${duration}px</span>
        </div>
    </div>`;
}

function tp_AutoSaveToDB(metaData, callback = null) {
    if (!tp_canAccessTimeline() || !metaData || !metaData.postId || !metaData.widgetId) {
        return;
    }

    jQuery.ajax({
        url: tp_ajax_obj.ajax_url,
        type: 'POST',
        dataType: 'json',
        data: {
            action: 'tp_save_gsap_timeline',
            post_id: metaData.postId,
            widget_id: metaData.widgetId,
            duration: metaData.duration,
            offset: metaData.offset,
            trigger: metaData.trigger,
            security: tp_ajax_obj.nonce
        },
        success: function (res) {
            if (res.success && callback) callback();
        }
    });
}

function tp_injectModalHTML() {
    if (document.getElementById('tp-custom-modal')) return;
    const html = `<div id="tp-custom-modal" class="tp-modal-overlay">
        <div class="tp-modal-box" style="position: relative;">
            <button id="tp-modal-close" class="tp-modal-close" type="button" aria-label="Close modal" style="position: absolute; top: 15px; right: 15px; cursor: pointer; font-size: 20px; line-height: 1; color: #333; z-index: 10; background: transparent; border: 0; padding: 0;">
                <i class="theplus-i-cross"></i>
            </button>
            <h3>Edit Animation</h3>
            <div class="tp-input-group">
                <div class="tp-input-label">
                    <i class="theplus-i-target"></i>
                    <label>Trigger</label>
                </div>
                <input type="number" step="0.1" id="tp-input-trigger">
            </div>
            <div class="tp-input-group">
                <div class="tp-input-label">
                    <i class="theplus-i-duration"></i>
                    <label>Duration</label>
                </div>
                <input type="number" id="tp-input-duration">
            </div>
            <div class="tp-input-group">
                <div class="tp-input-label">
                    <i class="theplus-i-move"></i>
                    <label>Offset</label>
                </div>
                <input type="number" id="tp-input-offset">
            </div>
            <div class="tp-modal-btns">
                <button id="tp-btn-cancel">Cancel</button>
                <button id="tp-btn-save">Save</button>
            </div>
        </div>
    </div>`;
    document.body.insertAdjacentHTML('beforeend', html);
}

function tp_injectTimelineControls(el) {
    if (el.querySelector('.tp-move-handle')) return;
    el.insertAdjacentHTML('afterbegin', `
        <div class="tp-move-handle">
            <span class="tp-timeline-heading">GSAP EDITOR</span>
            <div class="tp-btn-group">
                <button class="tp-ctrl-btn tp-play-btn" id="tp-auto-scroll-btn" title="Toggle Auto Scroll"><i class="theplus-i-play"></i><span class="tp-btn-text">Play</span></button>
                <button class="tp-ctrl-btn tp-hide-btn" id="tp-hide-timeline-btn" data-tooltip="You can hide or show the timeline with Ctrl + Shift + S." aria-label="You can hide or show the timeline with Ctrl + Shift + T."><i class="theplus-i-eye"></i>Hide</button>
            </div>
        </div>
    `);
    el.insertAdjacentHTML('beforeend', `
        <div class="tp-resizer tp-rs-t" data-dir="t"></div>
        <div class="tp-resizer tp-rs-b" data-dir="b"></div>
        <div class="tp-resizer tp-rs-l" data-dir="l"></div>
        <div class="tp-resizer tp-rs-r" data-dir="r"></div>
        <div class="tp-resizer tp-rs-br" data-dir="br"></div>
    `);
}

let _currentEditMeta = null;
function tp_openEditModal(meta) {
    _currentEditMeta = meta;
    document.getElementById('tp-input-duration').value = meta.duration;
    document.getElementById('tp-input-offset').value = meta.offset;
    document.getElementById('tp-input-trigger').value = meta.trigger;
    document.getElementById('tp-custom-modal').style.display = 'flex';
}
function tp_getModalMeta() { return _currentEditMeta; }

function tp_refreshTimelineLayout(el) {
    if (!el) return;

    const timelineNode = el.querySelector('.vis-timeline');
    if (timelineNode) {
        timelineNode.style.flex = '1';
        timelineNode.style.height = 'calc(100% - 50px)';
        timelineNode.style.minHeight = '0';
    }

    if (el._tpTimeline && typeof el._tpTimeline.redraw === 'function') {
        requestAnimationFrame(function () {
            el._tpTimeline.redraw();
        });
    }
}

function tp_setupWindowControls(el, win, doc) {
    const playBtn = el.querySelector('#tp-auto-scroll-btn');
    const playBtnText = playBtn ? playBtn.querySelector('.tp-btn-text') : null;
    const hideBtn = el.querySelector('#tp-hide-timeline-btn');
    let isPlaying = false, animationFrameId;

    function autoScroll() {
        if (!isPlaying) return;
        win.scrollBy(0, 3);
        animationFrameId = requestAnimationFrame(autoScroll);
        if ((win.innerHeight + win.scrollY) >= doc.body.offsetHeight) togglePlay();
    }

    function togglePlay() {
        isPlaying = !isPlaying;
        if (isPlaying) {
            if (playBtnText) playBtnText.textContent = 'Pause';
            playBtn.classList.add('playing');
            autoScroll();
        } else {
            if (playBtnText) playBtnText.textContent = 'Play';
            playBtn.classList.remove('playing');
            cancelAnimationFrame(animationFrameId);
        }
    }
    playBtn.addEventListener('click', togglePlay);

    function toggleVisibility() {
        el.style.display = (el.style.display === 'none') ? 'flex' : 'none';
    }
    hideBtn.addEventListener('click', toggleVisibility);

    document.addEventListener('keydown', function (e) {
        if (e.ctrlKey && e.shiftKey && (e.key === 's' || e.key === 'S')) {
            e.preventDefault();
            toggleVisibility();
        }
    });

    const handle = el.querySelector('.tp-move-handle');
    let isMoving = false, mX, mY, initL, initT;
    handle.addEventListener('mousedown', e => {
        if (e.target.closest('button')) return;
        isMoving = true; mX = e.clientX; mY = e.clientY;
        const r = el.getBoundingClientRect(); initL = r.left; initT = r.top;
        el.style.width = r.width + 'px'; el.style.height = r.height + 'px';
        el.style.bottom = 'auto'; el.style.right = 'auto';
        el.style.left = initL + 'px'; el.style.top = initT + 'px';
    });

    const resizers = el.querySelectorAll('.tp-resizer');
    let isResizing = false, dir = '', startX, startY, startW, startH, startL, startT;
    resizers.forEach(r => {
        r.addEventListener('mousedown', e => {
            e.stopPropagation(); e.preventDefault();
            isResizing = true; dir = r.dataset.dir;
            const rect = el.getBoundingClientRect();
            startX = e.clientX; startY = e.clientY;
            startW = rect.width; startH = rect.height;
            startL = rect.left; startT = rect.top;
            el.style.left = startL + 'px'; el.style.top = startT + 'px';
            el.style.bottom = 'auto'; el.style.right = 'auto';
        });
    });

    window.addEventListener('mousemove', e => {
        if (isMoving) {
            el.style.left = initL + (e.clientX - mX) + 'px';
            el.style.top = initT + (e.clientY - mY) + 'px';
        }
        if (isResizing) {
            const dx = e.clientX - startX;
            const dy = e.clientY - startY;
            if (dir.includes('r')) el.style.width = startW + dx + 'px';
            if (dir.includes('l')) { el.style.width = startW - dx + 'px'; el.style.left = startL + dx + 'px'; }
            if (dir.includes('b')) el.style.height = startH + dy + 'px';
            if (dir.includes('t')) { el.style.height = startH - dy + 'px'; el.style.top = startT + dy + 'px'; }
            tp_refreshTimelineLayout(el);
        }
    });

    window.addEventListener('mouseup', () => {
        isMoving = false;
        if (isResizing) {
            tp_refreshTimelineLayout(el);
        }
        isResizing = false;
    });
}
