// =====================================
// YouTube Video Tracker for Qualtrics
// =====================================

Qualtrics.SurveyEngine.addOnload(function() {    
    
    // ──────────────────────────────────────────────────────────────────────────────
    //                                 CONFIGURATION
    //    Edit *only* inside this block to change video IDs, thresholds, prompts
    // ──────────────────────────────────────────────────────────────────────────────
    const CONFIG = {
        // ─── Video source ─────────────────────────────────────────────────────────
        VIDEO_ID:      "unQTdWs5XVc",      
        YT_EMBED_FIELD:"YT_URL",       

        // ─── Viewing requirements ─────────────────────────────────────────────────
        WATCH_THRESHOLD: 90,               
        MIN_VIEWING_TIME: 85,              
        
        // ─── Skip & speed detection ──────────────────────────────────────────────
        SKIP_TOLERANCE: 3,                 
        MAX_SPEED_ALLOWED: 1.5,            
        SPEED_CHANGE_PENALTY: true,        
        FOCUS_LOSS_TOLERANCE: 10,          
        
        // ─── Mid-video prompt checkpoints  ───────────────────────────────────────
        CHECKPOINTS: [
            // {time: "1:30", qid:"QID3"},
            // {time: "0:30", note: "Hello, World!"}
        ],
        // ─── END EDITABLE SECTION ────────────────────────────────────────────────────────────────────
        

        // ─── Internals (leave these alone) ──────────────────────────────────────
        QP_EMBED: "QP",
        PROGRESS_CHECK_INTERVAL: 500,
        PLAYER_WIDTH: 640,
        PLAYER_HEIGHT: 360,
        STRICT_MODE: false,
        SHOW_PROGRESS: true,
        SHOW_VIOLATIONS: true
    };
    // ────────────────────────────────────────────────────────────────────────────

    
    /**
    * Convert "H:MM:SS", "M:SS" or "MM:SS" into total seconds.
    */
    function parseTimestamp(ts) {
        const parts = ts.split(':').map(Number);
        if (parts.length === 3) {
            return parts[0] * 3600 + parts[1] * 60 + parts[2];
        } else if (parts.length === 2) {
            return parts[0] * 60 + parts[1];
        } else {
            return parts[0];
        }
    }

    // Build a seconds→QID map and a seconds→note map
    const CHECKPOINT_QUESTIONS = {};
    const CHECKPOINT_NOTES     = {};
    CONFIG.CHECKPOINTS.forEach(({time, qid, note}) => {
    const sec = parseTimestamp(time);
    if (qid)  CHECKPOINT_QUESTIONS[sec] = qid;
    if (note) CHECKPOINT_NOTES[sec]     = note;
    });

    // Initialize which checkpoints have shown
    const checkpointTimes = CONFIG.CHECKPOINTS.map(c => parseTimestamp(c.time));
    const promptStatus    = {};
    checkpointTimes.forEach(sec => promptStatus[sec] = false);


    // CRITICAL: only run on the “video” question (no text inputs)
    const isVideoQuestion = this.questionContainer && 
                           this.questionContainer.innerHTML && 
                           !this.questionContainer.innerHTML.includes('input') && 
                           !this.questionContainer.innerHTML.includes('textarea');
    
    // If this is not the video question (i.e., it's a regular question), exit immediately
    if (!isVideoQuestion) {
        console.log('This is not the video question - script will not run');
        return;
    }
    console.log('Initializing YouTube tracker on video question...');

    // ────────────────────────────────
    //               STATE
    // ────────────────────────────────
    const state = {
        // YouTube player instance & overall watched flag
        player: null,
        hasWatched: false,

        // Time tracking
        lastCurrentTime: 0,
        totalWatchTime: 0,
        watchStartTime: null,

        // Focus/Loss detection
        focusLossTime: 0,
        focusLossStart: null,
        isVideoFocused: true,

        // Playback violations
        playbackRateChanged: false,
        skipViolations: [],
        maxTimeReached: 0,
        skipSuppress: 0,

        // Rewind tracking
        rewindEvents: [],
        rewindHotspots: {},
        
        // Aggregated analytics
        analytics: {
            totalSkips: 0,
            forwardSkips: 0,
            focusLosses: 0,
            speedChanges: 0,
            watchingTime: 0,
            restarts: 0,
            totalRewinds: 0

        }
    };
    // ────────────────────────────────


    // ────────────────────────────────
    //              HELPERS
    // ────────────────────────────────
    const utils = {
        /**
        * Update the main status banner (green/yellow/red).
        * @param {string} message – text to display
        * @param {"success"|"warning"|"error"} [type] – CSS class suffix
        */
        updateStatus(message, type) {
            if (elements.status) {
                elements.status.textContent = message;
                elements.status.className = 'yt-status ' + (type || '');
            }
        },

        /* Flash a red "Skip detected" strip just under teh banner */
        showSkipWarning(message) {
            let warningElement = document.getElementById('skip-warning');
            if (!warningElement) {
                warningElement = document.createElement('div');
                warningElement.id = 'skip-warning';
                warningElement.className = 'yt-skip-warning';
                elements.status.parentNode.insertBefore(warningElement, elements.status.nextSibling);
            }
            warningElement.textContent = message;
            warningElement.style.display = 'block';
            
            setTimeout(() => {
                if (warningElement) {
                    warningElement.style.display = 'none';
                }
            }, 5000);
        },

        /* Safely call YT.Player methods (returns null on error) */
        safePlayerCall(methodName, ...args) {
            try {
                if (state.player && typeof state.player[methodName] === 'function') {
                    return state.player[methodName](...args);
                }
            } catch (error) {
                console.error('YouTube player error:', error);
            }
            return null;
        },

        /* Push a skip / focus/ speed violation to memory + Embedded-Data */
        logSkipViolation(type, details) {
            const violation = {
                type: type,
                time: new Date().toISOString(),
                currentTime: utils.safePlayerCall('getCurrentTime'),
                details: details
            };
            state.skipViolations.push(violation);
            const count = state.skipViolations.length;

            // build the message with concatenation so the number can’t vanish
            const msg = 
                'Video is playing (' +
                count +
                ' violation' +
                (count === 1 ? '' : 's') +
                ')';

            console.log('🛑  DEBUG – count:', count, '→ msg:', msg);
            utils.updateStatus(msg, 'success');


            // after state.analytics.totalSkips = state.skipViolations.length;
            Qualtrics.SurveyEngine.setEmbeddedData('totalSkips', state.analytics.totalSkips);
            Qualtrics.SurveyEngine.setEmbeddedData('forwardSkips', state.analytics.forwardSkips);
            Qualtrics.SurveyEngine.setEmbeddedData('backwardSkips', state.analytics.backwardSkips);
            Qualtrics.SurveyEngine.setEmbeddedData('focusLosses', state.analytics.focusLosses);
            Qualtrics.SurveyEngine.setEmbeddedData('speedChanges', state.analytics.speedChanges);

        },

        /* % Runtime actually watched */
        calculateWatchingEfficiency() {
            const totalDuration = utils.safePlayerCall('getDuration');
            if (!totalDuration || totalDuration === 0) return 0;
            
            const efficiency = (state.totalWatchTime / totalDuration) * 100;
            const clampedEfficiency = Math.min(Math.max(efficiency, 0), 100);
            
            console.log('Efficiency calc: ' + state.totalWatchTime + 's watched / ' + totalDuration + 's total = ' + clampedEfficiency.toFixed(1) + '%');
            
            return clampedEfficiency;
        },

        /* Detect forward/backward jumps beyond normal play-head movement */
        isSkipDetected(currentTime, lastTime) {
            const timeDiff = currentTime - lastTime;
            const timeDiffAbs = Math.abs(timeDiff);
            
            const minSkipThreshold = CONFIG.SKIP_TOLERANCE || 3;
            const maxNormalProgress = 2;
            
            const isForwardSkip = timeDiff > maxNormalProgress && timeDiffAbs > minSkipThreshold;
            const isBackwardSkip = timeDiff < -minSkipThreshold;
            
            return {
                detected: isForwardSkip || isBackwardSkip,
                forward: isForwardSkip,
                backward: isBackwardSkip,
                amount: timeDiffAbs
            };
        }
    };

    // seconds -> "HH:MM:SS" string
    function formatTime(sec) {
        const h = Math.floor(sec/3600);
        const m = Math.floor((sec%3600)/60);
        const s = Math.floor(sec%60);
        return [h,m,s].map(n => String(n).padStart(2,'0')).join(':');
    }
    

    // Shared DOM elements holder
    let elements = {};
   
    function hideNextButton() {
        console.log('Attempting to disable navigation...');
        
        const forms = document.querySelectorAll('form');
        forms.forEach(form => {
            form.addEventListener('submit', function(e) {
                if (!state.hasWatched) {
                    e.preventDefault();
                    e.stopPropagation();
                    console.log('Blocked form submission - video not completed');
                    alert('Please watch the complete video before proceeding.');
                    return false;
                }
            });
            console.log('Added form submission blocker');
        });
        
        // Refined click guard: only blocks real nav buttons
        document.addEventListener('click', function(e) {
            if (state.hasWatched) return;

            const navBtn = e.target.closest(
                '#NextButton, .NextButton, button[type="submit"], input[type="submit"]'
            );

            if (!navBtn) return;

            e.preventDefault();
            e.stopPropagation();
            console.log('Blocked navigation click while video unfinished');
            alert('Please watch the complete video before proceeding')
            return false

            },
            true            
        );
        
        document.addEventListener('keydown', function(e) {
            if (!state.hasWatched) {
                if (e.key === 'Enter' || (e.key === 'Tab' && e.target.type === 'submit')) {
                    e.preventDefault();
                    e.stopPropagation();
                    console.log('Blocked keyboard navigation');
                    alert('Please watch the complete video before proceeding.');
                    return false;
                }
            }
        }, true);
        
        const hideButtonCSS = `
            <style id="hide-next-button">
                input[type="submit"]:not([data-video-allowed]),
                button[type="submit"]:not([data-video-allowed]),
                .NextButton:not([data-video-allowed]),
                #NextButton:not([data-video-allowed]),
                input[value*="Next"]:not([data-video-allowed]),
                input[value*="Continue"]:not([data-video-allowed]),
                input[value*="Submit"]:not([data-video-allowed]),
                .Buttons input:not([data-video-allowed]),
                .Buttons button:not([data-video-allowed]) {
                    display: none !important;
                    visibility: hidden !important;
                    opacity: 0 !important;
                    pointer-events: none !important;
                }
            </style>
        `;
        
        if (!document.getElementById('hide-next-button')) {
            document.head.insertAdjacentHTML('beforeend', hideButtonCSS);
            console.log('CSS navigation blocking added');
        }
        
        
        
        console.log('Navigation blocking initialized');
    }

    function showNextButton() {
        console.log('ENABLING navigation - video completed');
        
        // Remove our hide-next CSS
        const hideButtonStyle = document.getElementById('hide-next-button');
        if (hideButtonStyle) {
            hideButtonStyle.remove();
            console.log('Removed CSS navigation blocking');
        }
        
        // Remove the floating "video-notice" if it exists
        var notice = document.getElementById('video-notice');
        if (notice) {
            notice.parentNode.removeChild(notice);
            console.log('Removed completion notice');
        }
        
        // Force hide the locked-message banner
        var locked = document.getElementById('locked-message');
        if (locked) {
            locked.style.setProperty('display','none','important');
            console.log('Hidden locked message');
        }
        
        state.hasWatched = true;
        
        // Re-enable any "Next/Continue" buttons in the page
        const allElements = document.querySelectorAll('input, button, a, [role="button"]');
        let foundExisting = 0;
        
        allElements.forEach(el => {
            const text = (el.textContent || el.value || '').toLowerCase();
            const isNavigation = 
                text.includes('next') || text.includes('continue') || 
                text.includes('submit') || text.includes('forward') ||
                text === '→' || text === '>' ||
                el.type === 'submit';
             
            if (!isNavigation) return;
            
            foundExisting++;
            el.setAttribute('data-video-allowed', 'true');
            el.style.display = '';
            el.style.visibility = 'visible';
            el.style.opacity = '1';
            el.style.pointerEvents = 'auto';
            el.disabled = false;
                
            // Enhanced styling for existing buttons
            el.style.border = '3px solid #28a745';
            el.style.backgroundColor = '#d4edda';
            el.style.fontWeight = 'bold';
            el.style.padding = '10px 15px';
            el.style.borderRadius = '5px';
                
            // Add click handler to ensure proper navigation
            el.addEventListener('click', () => {
                console.log('Allowed Qualtrics navigation');
                state.hasWatched = true;
                const css = document.getElementById('hide-next-button');
                if (css) css.remove();
                });
        });

            console.log('Navigation enabled: ' + foundExisting + ' elements');
    }

    

    let ticker = null;

    function startTicker () {
        if (ticker) return;       // already running
        ticker = setInterval(() => {
            checkWatchProgress();   // run the existing logic once per tick
        }, CONFIG.PROGRESS_CHECK_INTERVAL);
    }

    function stopTicker () {
        if (!ticker) return;
        clearInterval(ticker);
        ticker = null;
    }
    /* ─── helper: pull ID from full YouTube link ─── */
    function extractVideoId(urlOrId) {
        // matches youtu.be/abc, youtube.com/watch?v=abc, etc.
        const m = urlOrId.match(/(?:v=|\/)([0-9A-Za-z_-]{11})(?:[\?&#]|$)/);
        return m ? m[1] : urlOrId.trim();   // if already 11-char, return as-is
    }


    /* ---------- Mid‑video prompt --------------------- */
    function showPrompt(sec) {
        // force exit fullscreen to answer prompt
        if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen();
            }
        }
        
        stopTicker();
        state.player.pauseVideo();

        // 1) grab optional question element
        const qid = CHECKPOINT_QUESTIONS[sec];
        let originalEl = null;
        let placeholder = null;
        if (qid) {
            originalEl = document.getElementById(qid);
            if (originalEl) {
                // stash a placeholder so we can restore later
                placeholder = document.createElement("div");
                originalEl.parentNode.replaceChild(placeholder, originalEl);
            }
        }

        // 2) build the overlay container
        const overlay = document.createElement("div");
        overlay.style.cssText = `
            position:fixed; inset:0;
            background:rgba(0,0,0,0.65);
            display:flex; justify-content:center; align-items:center;
            z-index:9999;
        `;
        const box = document.createElement("div");
        box.style.cssText = `
            background:#fff; padding:32px; border-radius:8px;
            max-width:80%; max-height:80%; overflow:auto;
            text-align:left;
        `;

        // 3) show professor’s note if you have one
        const noteText = CHECKPOINT_NOTES[sec] || "";

        if (noteText) {
            const noteEl = document.createElement("div");
            noteEl.style.cssText = "font-size:20px; margin-bottom:16px;";
            noteEl.textContent = noteText;
            noteEl.style.whiteSpace = "pre-wrap"
            box.appendChild(noteEl);
        }

        // 4) if there’s a checkpoint question, style & append it
        if (originalEl) {
            originalEl.style.display = "";

            // Question text
            const qText = originalEl.querySelector('.QuestionText');
            if (qText) {
                qText.style.cssText = "font-size:30px; font-weight:bold; margin-bottom:12px;";
            }
            // Radios / checkboxes
            originalEl.querySelectorAll('input[type="radio"], input[type="checkbox"]').forEach(el => {
                const ctr = el.parentElement;
                ctr.style.cssText = "display:flex; align-items:center; margin:12px 0; font-size:20px;";
                el.style.marginRight = '8px';
            });
            // Textareas
            originalEl.querySelectorAll('textarea').forEach(t => {
                t.rows = 5;
                t.style.cssText = "font-size:20px; padding:10px 12px; box-sizing:border-box; width:100%; height:140px; resize:vertical;";
                const tip = document.createElement('div');
                tip.textContent = 'Tip: drag bottom‑right to resize.';
                tip.style.cssText = 'font-size:16px;color:#666;margin-top:4px;';
                t.parentElement.appendChild(tip);
            });

            box.appendChild(originalEl);
        }

        // 5) Continue button
        const btn = document.createElement("button");
        btn.textContent = "Continue";
        btn.style.cssText = "margin-top:20px; padding:10px 20px; font-size:16px;";
        btn.onclick = () => {
            if (originalEl && placeholder) {
                placeholder.parentNode.replaceChild(originalEl, placeholder);
                originalEl.style.display = 'none';
            }
            // 5.1) remove the overlay from parent
            if (overlay.parentNode) {
                overlay.parentNode.removeChild(overlay);
            }
            state.player.playVideo();
            startTicker();
        };
        box.appendChild(btn);

        // 6) show it
        overlay.appendChild(box);

        // Find the player container (the parent of the YouTube iframe)
        const playerContainer = document.querySelector('.yt-player-container');

        // Check if the player container is in fullscreen
        const fsElement = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;

        if (fsElement && playerContainer && fsElement.contains(playerContainer)) {
            // Append overlay to player container so it shows in fullscreen
            playerContainer.appendChild(overlay);
        } else if (playerContainer) {
            // Not in fullscreen, append to player container for proper stacking
            playerContainer.appendChild(overlay);
        } else {
            // Fallback
            document.body.appendChild(overlay);
        }
    }

    function createVideoInterface() {
        if (!document.getElementById('yt-video-styles')) {
            document.head.insertAdjacentHTML('beforeend', styles);
        }

        const interfaceHTML = `
            <div class="yt-video-container">
                <div class="yt-player-container">
                    <div id="player"></div>
                </div>
                
                <div id="yt-status" class="yt-status" role="status" aria-live="polite">
                    Loading video player...
                </div>
                <div id="locked-message" class="yt-locked-message">
                    You must watch the complete video without skipping to proceed to the next questions.
                </div>
            </div>
        `;

        this.questionContainer.innerHTML = interfaceHTML;

        elements = {
            status: document.getElementById("yt-status"),
        };

        console.log('Video interface created successfully');
        return true;
    }

    function initializeFocusDetection() {
        document.addEventListener('visibilitychange', () => {
            if (document.hidden) {
                if (state.isVideoFocused) {
                    state.focusLossStart = Date.now();
                    state.isVideoFocused = false;
                    state.analytics.focusLosses++;
                    console.log('Focus lost - tab/window hidden');
                }
            } else {
                if (!state.isVideoFocused && state.focusLossStart) {
                    const focusLossDuration = (Date.now() - state.focusLossStart) / 1000;
                    state.focusLossTime += focusLossDuration;
                    state.isVideoFocused = true;
                    
                    console.log('Focus regained after focus loss');
                    
                    if (focusLossDuration > CONFIG.FOCUS_LOSS_TOLERANCE) {
                        utils.logSkipViolation('focus_loss', {
                            duration: focusLossDuration,
                            totalFocusLoss: state.focusLossTime
                        });
                        utils.showSkipWarning('Focus loss detected! Please keep the window active while watching.');
                    }
                }
            }
        });

        window.addEventListener('focus', () => {
            if (!state.isVideoFocused && state.focusLossStart) {
                const focusLossDuration = (Date.now() - state.focusLossStart) / 1000;
                state.focusLossTime += focusLossDuration;
                state.isVideoFocused = true;
                
                if (focusLossDuration > CONFIG.FOCUS_LOSS_TOLERANCE) {
                    utils.logSkipViolation('focus_loss', {
                        duration: focusLossDuration,
                        totalFocusLoss: state.focusLossTime
                    });
                }
            }
        });

        window.addEventListener('blur', () => {
            if (state.isVideoFocused) {
                state.focusLossStart = Date.now();
                state.isVideoFocused = false;
                state.analytics.focusLosses++;
            }
        });
    }

    window.onYouTubeIframeAPIReady = function() {
        console.log('YouTube API ready, creating player...');
        
        try {
            const edUrl  = Qualtrics.SurveyEngine.getEmbeddedData(CONFIG.YT_EMBED_FIELD) || "";
            const finalId = extractVideoId(edUrl) || CONFIG.VIDEO_ID;
            state.player = new YT.Player('player', {
                height: CONFIG.PLAYER_HEIGHT,
                width: CONFIG.PLAYER_WIDTH,
                videoId: finalId,
                playerVars: { 
                    rel: 0, 
                    modestbranding: 1,
                    enablejsapi: 1
                },
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange,
                    'onError': onPlayerError,
                    'onPlaybackRateChange': onPlaybackRateChange
                }
            });
        } catch (error) {
            console.error('Failed to create YouTube player:', error);
            utils.updateStatus("Failed to create video player: " + error.message, "error");
        }
    };

    function onPlayerReady(event) {
        if (Qualtrics.SurveyEngine.getEmbeddedData('videoWatched') === 'Yes') {
            try { Qualtrics.SurveyEngine.enableNextButton() } catch(e){}
            showNextButton();
            return;
        }

        try {
            console.log('Player ready - Duration:', state.player.getDuration(), 'seconds');
            utils.updateStatus("Video loaded! You must watch the complete video without skipping to proceed.", "success");
            
            try {
                if (typeof Qualtrics !== 'undefined' && 
                    Qualtrics.SurveyEngine && 
                    typeof Qualtrics.SurveyEngine.disableNextButton === 'function') {
                    Qualtrics.SurveyEngine.disableNextButton();
                    console.log('Qualtrics disableNextButton called');
                }
            } catch (e) {
                console.log('Qualtrics disableNextButton not available');
            }
            
            hideNextButton();
            initializeFocusDetection();
        } catch (error) {
            console.error('Player ready error:', error);
            hideNextButton();
        }
    }

    function onPlayerStateChange(event) {
        if (Qualtrics.SurveyEngine.getEmbeddedData('videoWatched') === 'Yes') {
            try { Qualtrics.SurveyEngine.enableNextButton() } catch(e){}
            showNextButton();
            return;
        }

        try {
            if (event.data === YT.PlayerState.PLAYING) {
                handleVideoPlaying();
            } else if (event.data === YT.PlayerState.ENDED) {
                
                const totalDur = utils.safePlayerCall('getDuration') || 1;

                if (totalDur - state.lastCurrentTime > CONFIG.SKIP_TOLERANCE) {
                    console.log('Detected a jump-to-end skip');
                    handleForwardSkip(totalDur - state.lastCurrentTime);
                    return
                }
                // mark as “watched” once we actually get to the end
                Qualtrics.SurveyEngine.setEmbeddedData('videoWatched', 'Yes');
                handleVideoEnded();
            } else if (event.data === YT.PlayerState.PAUSED) {
                handleVideoPaused();
            }
        } catch (error) {
            console.error('Player state change error (this is normal):', error.message);
        }
    }

    function onPlaybackRateChange(event) {
        if (Qualtrics.SurveyEngine.getEmbeddedData('videoWatched') === 'Yes') {
            try { Qualtrics.SurveyEngine.enableNextButton() } catch(e){}
            showNextButton();
            return;
        }

        const rate = event.data;
        if (CONFIG.MAX_SPEED_ALLOWED && rate > CONFIG.MAX_SPEED_ALLOWED && CONFIG.SPEED_CHANGE_PENALTY) {
            state.playbackRateChanged = true;
            state.analytics.speedChanges++;
            
            utils.logSkipViolation('speed_change', {
                newRate: rate,
                previousRate: 1
            });
            
            utils.showSkipWarning('Playback speed changed. Please watch at normal speed.');
            
            setTimeout(() => {
                utils.safePlayerCall('setPlaybackRate', 1);
            }, 1000);
        }
    }

    function onPlayerError(event) {
        console.error('YouTube player error:', event.data);
        utils.updateStatus("Video failed to load. Please check the video ID or refresh the page.", "error");
    }

    function handleVideoPlaying() {
        state.watchStartTime = Date.now();

        if (!state.hasWatched) {
            const count = state.skipViolations.length;

             if (count > 0) {
                // build with concatenation so count can’t disappear
                const msg =
                    'Video is playing (' +
                    count +
                    ' violation' +
                    (count === 1 ? '' : 's') +
                    ')';
                utils.updateStatus(msg, 'success');
            } else {
                utils.updateStatus(
                    'Video is playing. You must watch completely without skipping to proceed!',
                    'success'
                );
            }

            startTicker();
        }
    }

    function handleVideoPaused() {
        stopTicker();

        if (state.watchStartTime) {
            const sessionDuration = (Date.now() - state.watchStartTime) / 1000;
            state.totalWatchTime += sessionDuration;
            state.analytics.watchingTime = state.totalWatchTime;
            state.watchStartTime = null;
            console.log('Video paused. Session: ' + sessionDuration + 's, Total: ' + state.totalWatchTime + 's');
        }
    }

    function handleVideoEnded() {
        console.log('VIDEO ENDED - Evaluating watch quality');
        
        stopTicker();
        
        // Finish up total watch time
        if (state.watchStartTime) {
            const finalSessionDuration = (Date.now() - state.watchStartTime) / 1000;
            state.totalWatchTime += finalSessionDuration;
            state.watchStartTime = null;
        }
        
        // Calculate efficiency
        const totalDuration = utils.safePlayerCall('getDuration') || 1;
        const efficiency = utils.calculateWatchingEfficiency();
        state.analytics.watchingTime = state.totalWatchTime;
        
        // debug: show raw analytics
        console.log('Watch Analytics:', {
            efficiency: efficiency,
            totalWatchTime: state.totalWatchTime,
            videoDuration: totalDuration,
            skipViolations: state.skipViolations.length,
            focusLossTime: state.focusLossTime,
            analytics: state.analytics
        });
        
        // Determine Good vs Poor
        const hasSkipViolations = state.skipViolations.length > 0;
        const hasExcessiveFocusLoss = state.focusLossTime > CONFIG.FOCUS_LOSS_TOLERANCE;
        const hasSpeedViolations = CONFIG.SPEED_CHANGE_PENALTY && state.playbackRateChanged;
        const watchedProperly = (
            efficiency >= CONFIG.MIN_VIEWING_TIME &&
            !hasSkipViolations &&
            !hasExcessiveFocusLoss &&
            !hasSpeedViolations
        );
        
        // debug: show quality decision
        console.log('Watch Quality Check:', {
            efficiency: efficiency,
            minRequired: CONFIG.MIN_VIEWING_TIME,
            skipViolations: hasSkipViolations,
            focusLoss: hasExcessiveFocusLoss,
            speedViolations: hasSpeedViolations,
            watchedProperly: watchedProperly
        });

        // Calulate average rewind length
        const totalRewinds = state.rewindEvents.length;
        const avgRewind = totalRewinds ? state.rewindEvents.reduce((sum,e)=> sum + e.amount, 0) / totalRewinds : 0;

        // push into Embedded Data
        Qualtrics.SurveyEngine.setEmbeddedData('totalRewinds',    totalRewinds);
        Qualtrics.SurveyEngine.setEmbeddedData('rewindEvents',    JSON.stringify(state.rewindEvents));
        Qualtrics.SurveyEngine.setEmbeddedData('avgRewindLength', avgRewind.toFixed(1));
        
        // Snapshot each metric into its own field
        Qualtrics.SurveyEngine.setEmbeddedData('videoWatched',     'Yes');
        Qualtrics.SurveyEngine.setEmbeddedData('watchQuality',     watchedProperly ? 'Good' : 'Poor');
        Qualtrics.SurveyEngine.setEmbeddedData('watchEfficiency',  efficiency.toFixed(1));
        Qualtrics.SurveyEngine.setEmbeddedData('watchingTime',     state.totalWatchTime.toFixed(1));
        Qualtrics.SurveyEngine.setEmbeddedData('finalSkipViolations', JSON.stringify(state.skipViolations));

        // Completion logic
        if (watchedProperly || !CONFIG.STRICT_MODE) {
            state.hasWatched = true;
            utils.updateStatus("Video completed successfully. The Next button is now available!", "success");
            
            if (elements.lockedMessage) {
                elements.lockedMessage.style.display = "none";
            }
            
            console.log('VIDEO COMPLETED SUCCESSFULLY - SHOWING NEXT BUTTON');
            console.log('Watch quality details:', {
                efficiency: efficiency,
                skipViolations: state.skipViolations.length,
                focusLoss: state.focusLossTime,
                watchedProperly: watchedProperly
            });
            
            try {
                if (typeof Qualtrics !== 'undefined' && 
                    Qualtrics.SurveyEngine && 
                    typeof Qualtrics.SurveyEngine.enableNextButton === 'function') {
                    Qualtrics.SurveyEngine.enableNextButton();
                    console.log('Qualtrics enableNextButton called');
                } else {
                    console.log('Qualtrics enableNextButton not available - using manual methods');
                }
            } catch (e) {
                console.log('Qualtrics API failed (expected):', e.message);
            }
            
            showNextButton();
            
            setTimeout(() => {
                const nextBtn = document.querySelector('#NextButton, .NextButton, input[value*="Next"], button[title*="Next"]');
                if (nextBtn) {
                    const isVisible = nextBtn.offsetHeight > 0 && nextBtn.offsetWidth > 0;
                    console.log('Next button visibility check:', isVisible);
                    if (!isVisible) {
                        console.log('Button not visible, forcing display again');
                        showNextButton();
                    }
                } else {
                    console.log('Next button not found, attempting to show again');
                    showNextButton();
                }
            }, 1000);
            
            Qualtrics.SurveyEngine.setEmbeddedData("watchQuality", watchedProperly ? "Good" : "Poor");
            Qualtrics.SurveyEngine.setEmbeddedData("watchEfficiency", efficiency.toFixed(1));
        } else {
            // Poor quality branch
            utils.updateStatus("Video viewing quality insufficient. Please watch again without skipping.", "warning");
            utils.showSkipWarning("You need to watch the video more carefully. Click play to restart.");
            
            try {
                if (typeof Qualtrics !== 'undefined' && 
                    Qualtrics.SurveyEngine && 
                    typeof Qualtrics.SurveyEngine.disableNextButton === 'function') {
                    Qualtrics.SurveyEngine.disableNextButton();
                    console.log('Qualtrics disableNextButton called');
                }
            } catch (e) {
                console.log('Qualtrics API failed:', e.message);
            }
            
            hideNextButton();
            
            state.analytics.restarts++;
            
            setTimeout(() => {
                utils.safePlayerCall('seekTo', 0);
                utils.safePlayerCall('pauseVideo');
                
                state.hasWatched = false;
                state.totalWatchTime = 0;
                state.skipViolations = [];
                state.focusLossTime = 0;
                state.playbackRateChanged = false;
                state.lastCurrentTime = 0;
                state.maxTimeReached = 0;
            }, 2000);
        }
        state.analytics.totalSkips = state.skipViolations.length;

        Qualtrics.SurveyEngine.setEmbeddedData("finalAnalytics", JSON.stringify(state.analytics));
    }

    function checkWatchProgress() {
        if (Qualtrics.SurveyEngine.getEmbeddedData('videoWatched') === 'Yes') {
            try { Qualtrics.SurveyEngine.enableNextButton() } catch(e){}
            showNextButton();
            return;
        }
        const currentTime = utils.safePlayerCall('getCurrentTime');
        const totalDuration = utils.safePlayerCall('getDuration');

        if (!currentTime || !totalDuration) return;

        const skipInfo = utils.isSkipDetected(currentTime, state.lastCurrentTime);
        if (skipInfo.detected) {
            console.log('Skip detected', skipInfo);
            if (skipInfo.forward) {
                state.analytics.forwardSkips++;
                handleForwardSkip(skipInfo.amount);
            }
            else {
                state.analytics.backwardSkips++;
                handleBackwardSkip(skipInfo.amount);
            }
        return;
        }

        // 2) keep the old time so we can detect crossings
        const prevTime = state.lastCurrentTime;

        // 3) your existing progress logging / status update…
        if (CONFIG.SHOW_PROGRESS) {
            const count = state.skipViolations.length;
            if (count > 0) {
                const msg =
                'Video is playing (' +
                count +
                ' violation' +
                (count === 1 ? '' : 's') +
                ')';
                utils.updateStatus(msg, 'success');
            }
            // but if count===0, do *nothing*—we leave whatever message was last set
        }
        // 4) trigger checkpoint when we cross the timestamp
        checkpointTimes.forEach(sec => {
            if (!promptStatus[sec] &&
                prevTime < sec &&
                currentTime       >= sec
            ) {
                promptStatus[sec] = true;
                showPrompt(sec);
            }
        });

        state.lastCurrentTime = currentTime;
            
    }

    function handleForwardSkip(amount) {
        console.log('Forward skip detected: ' + amount + ' seconds');
        
        utils.logSkipViolation('forward_skip', {
            amount: amount,
            fromTime: state.lastCurrentTime,
            toTime: utils.safePlayerCall('getCurrentTime')
        });
        
        if (CONFIG.STRICT_MODE || amount > CONFIG.SKIP_TOLERANCE) {
            utils.showSkipWarning('Forward skip detected! Please watch without skipping.');
            
            utils.safePlayerCall('seekTo', state.lastCurrentTime);

            // Clear any check-points that are now "ahead" of the viewer
            const newPosition = state.lastCurrentTime;
            const duration = utils.safePlayerCall('getDuration') || 1;
            Object.keys(promptStatus).forEach(cp => {
                if (newPosition < cp * duration) {
                    promptStatus[cp] = false;   // User hasn't legitimately reached it yet
                }
            });

            state.skipSuppress = Date.now() + CONFIG.PROGRESS_CHECK_INTERVAL;
            state.lastCurrentTime = newPosition;
            utils.safePlayerCall('pauseVideo');
            
            setTimeout(() => {
                utils.updateStatus("Click play to continue from where you left off (no skipping allowed)", "warning");
            }, 2000);
        }
    }

    function handleBackwardSkip(amount) {
        const from = state.lastCurrentTime;
        const to   = utils.safePlayerCall('getCurrentTime');
        const event = {
            time:   new Date().toISOString(),
            from:   formatTime(from),
            to:     formatTime(to),
            amount: Number((from - to).toFixed(1))
        };

        // record
        state.rewindEvents.push(event);
        state.analytics.totalRewinds = state.rewindEvents.length;

        // track hotspot
        const minute = Math.floor(from/60);
        state.rewindHotspots[minute] = (state.rewindHotspots[minute]||0) + 1;

        // feedback & badge
        utils.showSkipWarning('Rewinded');

        // save immediately
        Qualtrics.SurveyEngine.setEmbeddedData('totalRewinds',   state.analytics.totalRewinds);
        Qualtrics.SurveyEngine.setEmbeddedData('rewindEvents',   JSON.stringify(state.rewindEvents));
        Qualtrics.SurveyEngine.setEmbeddedData('rewindHotspots', JSON.stringify(state.rewindHotspots));

        state.lastCurrentTime = to;
    }



    function cleanup() {
       
        Qualtrics.SurveyEngine.setEmbeddedData("finalSkipViolations", JSON.stringify(state.skipViolations));
        Qualtrics.SurveyEngine.setEmbeddedData("finalAnalytics", JSON.stringify(state.analytics));
    }

    createVideoInterface.call(this);

    if (typeof YT === 'undefined' || !YT.Player) {
        const youtubeScript = document.createElement('script');
        youtubeScript.src = 'https://www.youtube.com/iframe_api';
        document.body.appendChild(youtubeScript);
    } else {
        window.onYouTubeIframeAPIReady();
    }

    const already = Qualtrics.SurveyEngine.getEmbeddedData('videoWatched');
    if (already === 'Yes') {
        try { Qualtrics.SurveyEngine.enableNextButton();} catch (e) {}
        showNextButton();
        return;
    }  

    // ─── hide all checkpoint questions until needed ───
    Object.values(CHECKPOINT_QUESTIONS).forEach(qid => {
        const q = document.getElementById(qid);
        if (q) q.style.display = 'none';
    });
    
    
    hideNextButton();
    initializeFocusDetection();
    window.addEventListener('beforeunload', cleanup);
    
    this.stopTicker = cleanup;

});

Qualtrics.SurveyEngine.addOnUnload(function() {
    if (this.stopTicker) {
        this.stopTicker();
    }
    
    const styleElement = document.getElementById('yt-video-styles');
    if (styleElement) {
        styleElement.remove();
    }
});

const styles = `
        <style id="yt-video-styles">
            .yt-video-container {
                font-family: inherit;
                margin: 20px 0;
                text-align: center;
            }
            
            .yt-player-container {
                margin: 20px 0;
                display: inline-block;
            }
            
            .yt-status {
                font-weight: bold;
                margin: 15px 0;
                padding: 12px;
                border-radius: 6px;
                min-height: 20px;
                max-width: 600px;
                margin-left: auto;
                margin-right: auto;
            }
            
            .yt-status.success {
                background-color: #d4edda;
                color: #155724;
                border: 1px solid #c3e6cb;
            }
            
            .yt-status.warning {
                background-color: #fff3cd;
                color: #856404;
                border: 1px solid #ffeaa7;
            }
            
            .yt-status.error {
                background-color: #f8d7da;
                color: #721c24;
                border: 1px solid #f5c6cb;
            }
            
            .yt-skip-warning {
                background-color: #ff6b6b;
                color: white;
                padding: 15px;
                margin: 10px 0;
                border-radius: 8px;
                font-weight: bold;
                animation: pulse 2s infinite;
            }
            
            @keyframes pulse {
                0% { opacity: 1; }
                50% { opacity: 0.7; }
                100% { opacity: 1; }
            }
            
            .yt-locked-message {
                position: fixed !important;
                bottom: 0 !important;
                left: 0 !important;
                width: 100% !important;
                background-color: #dc3545 !important;
                color: white !important;
                padding: 12px 0 !important;
                font-weight: bold !important;
                font-size: 16px !important;
                text-align: center !important;
                z-index: 999999 !important;
                box-shadow: none !important;
                border-radius: 0 !important;
            }
            
            .yt-embedded-nav {
                margin-top: 30px;
                padding: 25px;
                text-align: center;
                border: 2px solid #28a745;
                border-radius: 12px;
                background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%);
                max-width: 500px;
                margin-left: auto;
                margin-right: auto;
            }
            
            .yt-next-button {
                background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
                color: white;
                border: none;
                padding: 15px 40px;
                font-size: 18px;
                font-weight: bold;
                border-radius: 8px;
                cursor: pointer;
                transition: all 0.3s ease;
                box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3);
                text-transform: uppercase;
                letter-spacing: 1px;
            }
            
            .yt-next-button:hover {
                transform: translateY(-2px);
                box-shadow: 0 6px 20px rgba(40, 167, 69, 0.4);
                background: linear-gradient(135deg, #218838 0%, #1e7e34 100%);
            }
            
            .yt-next-button:active {
                transform: translateY(0);
                box-shadow: 0 2px 10px rgba(40, 167, 69, 0.3);
            }
            
            .yt-next-button:disabled {
                background: #6c757d;
                cursor: not-allowed;
                transform: none;
                box-shadow: none;
            }

            @media (max-width: 768px) {
            .yt-player-container {
                width: 100% !important;
                position: relative;
                padding-top: 56.25%; /* 16:9 aspect ratio */
            }
            #player,
            #player iframe {
                position: absolute;
                top: 0;
                left: 0;
                width: 100% !important;
                height: 100% !important;
            }
            }
        </style>
`;
