<div class="exam-question-fragment">
    <!-- Flag button lives inside the fragment so it updates together with other question controls -->
    <form method="POST" class="post-form"
          hx-post="{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=pos cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=pos %}{% endif %}"
          hx-target="#question-fragment" hx-swap="innerHTML">
        {% csrf_token %}
        {{ form.non_field_errors }}

        <div class="form-contents">
            <!-- Mobile/fragment-visible copy of the question stem (kept hidden on md+ because main page shows it) -->
            <div class="question-stem-fragment d-md-none mb-2">{{ question.stem|safe }}</div>
            <ol class="physics-answer-list">
                <li data-ans="a">
                    <div class="fieldWrapper flex-container">
                        {{ form.a.errors }}
                        <label for="{{ form.a.id_for_label }}" class="flex-8 question-text">{{ question.a|safe }}</label>
                        <span class="flex-1">{{ form.a }}<span class="postinput"></span></span>
                    </div>
                    {% if exam.publish_results and question.a_feedback %}
                        <span class="feedback">Feedback: {{ question.a_feedback }}</span>
                    {% endif %}
                </li>

                <li data-ans="b">
                    <div class="fieldWrapper flex-container">
                        {{ form.b.errors }}
                        <label for="{{ form.b.id_for_label }}" class="flex-8 question-text">{{ question.b|safe }}</label>
                        <span class="flex-1">{{ form.b }}<span class="postinput"></span></span>
                    </div>
                    {% if exam.publish_results and question.b_feedback %}
                        <div class="mt-1"><small class="feedback text-muted">Feedback: {{ question.b_feedback|safe }}</small></div>
                    {% endif %}
                </li>

                <li data-ans="c">
                    <div class="fieldWrapper flex-container">
                        {{ form.c.errors }}
                        <label for="{{ form.c.id_for_label }}" class="flex-8 question-text">{{ question.c|safe }}</label>
                        <span class="flex-1">{{ form.c }}<span class="postinput"></span></span>
                    </div>
                    {% if exam.publish_results and question.c_feedback %}
                        <div class="mt-1"><small class="feedback text-muted">Feedback: {{ question.c_feedback|safe }}</small></div>
                    {% endif %}
                </li>

                <li data-ans="d">
                    <div class="fieldWrapper flex-container">
                        {{ form.d.errors }}
                        <label for="{{ form.d.id_for_label }}" class="flex-8 question-text">{{ question.d|safe }}</label>
                        <span class="flex-1">{{ form.d }}<span class="postinput"></span></span>
                    </div>
                    {% if exam.publish_results and question.d_feedback %}
                        <div class="mt-1"><small class="feedback text-muted">Feedback: {{ question.d_feedback|safe }}</small></div>
                    {% endif %}
                </li>

                <li data-ans="e">
                    <div class="fieldWrapper flex-container">
                        {{ form.e.errors }}
                        <label for="{{ form.e.id_for_label }}" class="flex-8 question-text">{{ question.e|safe }}</label>
                        <span class="flex-1">{{ form.e }}<span class="postinput"></span></span>
                    </div>
                    {% if exam.publish_results and question.e_feedback %}
                        <div class="mt-1"><small class="feedback text-muted">Feedback: {{ question.e_feedback|safe }}</small></div>
                    {% endif %}
                </li>
            </ol>
        </div>

        <div class="mt-2">
            <div class="d-flex align-items-center justify-content-between">
                <div class="btn-row">
                    {% if previous > -1 %}
                        <button type="submit" name="previous" class="save btn btn-secondary" title="Click to save your answer(s) and go to the previous question" onclick="try{ window.currentQuestionPos = {{ previous }}; if(typeof updateQuestionMenu==='function') updateQuestionMenu(); }catch(e){}">Previous</button>
                    {% endif %}

                    {% if next %}
                        <button type="submit" name="next" class="save btn btn-secondary" title="Click to save your answer(s) and go to the next question" onclick="try{ window.currentQuestionPos = {{ pos|add:1 }}; if(typeof updateQuestionMenu==='function') updateQuestionMenu(); }catch(e){}">Next</button>
                            <!-- Skip: load the next question fragment without submitting the form -->
                        <button type="button" id="skip-button" class="btn btn-outline-secondary ms-2" title="Skip to next question without saving"
                                hx-get="{% if cid %}{% url 'physics:exam_take_fragment' pk=exam.pk sk=pos|add:1 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_fragment_user' pk=exam.pk sk=pos|add:1 %}{% endif %}"
                                hx-target="#question-fragment" hx-swap="innerHTML">Skip</button>

                            <!-- Fallback link for non-HTMX clients: simple navigation without saving -->
                        <a class="d-none" href="{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=pos|add:1 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=pos|add:1 %}{% endif %}"></a>
                    {% else %}
                        {% if not exam.publish_results %}
                            <button type="submit" name="save" class="save btn btn-default" title="Click to save your current answer(s)">Save</button>
                        {% endif %}
                    {% endif %}

                    <br />
                    <button type="submit" id="overview-button" name="finish" class="save btn btn-default" title="Click to go to the overview page (your answers will be saved).">Overview</button>
                    <button type="submit" id="goto-button" value="test" name="goto" class="hide">goto</button>
                </div>

                <div class="flag-container ms-3">
                    {% include 'physics/partials/exam_flag_button.html' %}
                </div>
            </div>
        </div>
    </form>

    <script>
        (function () {
            /* run after fragment is loaded */
            // Update the global page header question number and stem so the top of the page stays in sync
            try {
                var qnum = document.getElementById('question-number');
                if (qnum) { qnum.textContent = '{{ pos|add:"1" }}'; }
                // expose current question index for global listeners
                window.currentQuestionPos = {{ pos }};
                var qstem = document.getElementById('question-stem');
                if (qstem) { qstem.innerHTML = '{{ question.stem|escapejs }}'; }
            } catch (err) {
                console.warn('Could not update global question header from fragment', err);
            }
            // expose current question index for global listeners
            window.currentQuestionPos = {{ pos }};
            // Update the browser URL to reflect the current question (so Prev/Next/Skip update URL)
            try {
                const pageUrlTemplate = `{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=0 %}{% endif %}`;
                const pageUrl = pageUrlTemplate.replace('/0/', '/' + window.currentQuestionPos + '/');
                history.replaceState(null, '', pageUrl);
            } catch (e) { /* ignore */ }
            {% if not exam.publish_results and not cid_user_exam.completed %}
                let time_limit = '{{ exam.time_limit }}';
                if (time_limit != 'None') {
                    let end_time = new Date({{ cid_user_exam.start_time|date:"U" }} * 1000 + parseInt('{{ exam.time_limit }}') * 1000);
                    if (typeof initializeClock === 'function') {
                        initializeClock('clockdiv', end_time);
                    }
                }

            {% elif exam.publish_results %}
                $('ol.physics-answer-list input').each((n, el) => { el.disabled = true; });
                {{ question.get_answers_js }}.forEach((el, n) => {
                    const li_el = $(`ol.physics-answer-list li:eq(${n})`);

                    if (el) {
                        li_el.addClass('answer-true');
                    } else {
                        li_el.addClass('answer-false');
                    }

                    if (el == li_el.find('input').get(0).checked) {
                        li_el.addClass('answer-correct');
                    } else {
                        li_el.addClass('answer-incorrect');
                    }
                });

            {% elif cid_user_exam.completed %}
                $('ol.physics-answer-list input').each((n, el) => { el.disabled = true; });
            {% endif %}

            // build the question menu locally so it is available after fragment swaps
            $('#menu-list').empty();
            const serverAnswered = {{ answered_json|default:'null'|safe }};
            const serverFlagged = {{ flagged_json|default:'null'|safe }};
            // Always refresh client-side arrays from server-provided state when fragment loads
            if (Array.isArray(serverAnswered)) {
                window.examQuestionAnswered = serverAnswered;
            }
            if (Array.isArray(serverFlagged)) {
                window.examQuestionFlagged = serverFlagged;
            }
            const answeredArr = (window.examQuestionAnswered && Array.isArray(window.examQuestionAnswered)) ? window.examQuestionAnswered : null;
            const flaggedArr = (window.examQuestionFlagged && Array.isArray(window.examQuestionFlagged)) ? window.examQuestionFlagged : null;
            for (let i = 0; i < {{ exam_length }}; i++) {
                const qbutton = $(`<button class="question-menu-item" name="goto-${i}" data-qn="${i}"><span class="qnum">${i+1}</span></button>`);
                if (answeredArr && answeredArr[i]) { qbutton.addClass('answered'); }
                if (flaggedArr && flaggedArr[i]) {
                    qbutton.addClass('flagged');
                    // ensure flag icon exists only once
                    if (qbutton.find('.question-flag').length === 0) qbutton.append('<span class="question-flag" aria-hidden="true">⚑</span>');
                }
                if (i == {{ pos }}) { qbutton.addClass('current-question'); }
                $('#menu-list').append(qbutton);
            }

            // Let a central updater ensure classes are consistent (handles cases where menu exists before arrays)
            if(typeof window.updateQuestionMenu === 'function') window.updateQuestionMenu();

            // Template URL for loading a fragment — use sk=0 as placeholder to replace later
            const fragUrlTemplate = `{% if cid %}{% url 'physics:exam_take_fragment' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_fragment_user' pk=exam.pk sk=0 %}{% endif %}`;

            // Use event delegation on the menu list to reliably catch clicks
            (function(){
                const menu = document.getElementById('menu-list');
                if(!menu) return;
                if(menu.dataset.delegateBound) return; // idempotent
                menu.dataset.delegateBound = '1';
                menu.addEventListener('click', function(e){
                    const btn = e.target.closest && e.target.closest('.question-menu-item');
                    if(!btn) return;
                    const destIndex = btn.dataset.qn;
                    try{
                        const allFalse = Array.from(document.querySelectorAll('ol.physics-answer-list li')).every(li => {
                            const inp = li.querySelector('input');
                            return !(inp && inp.checked);
                        });

                        if(allFalse){
                            // Use modal prompt instead of native confirm
                            try{
                                // prevent default while we prompt
                                e.preventDefault(); e.stopImmediatePropagation();
                            }catch(ex){}
                            openSaveSkipModal('All answers are false. Save these answers or skip without saving?').then(function(choice){
                                if(choice === 'save'){
                                    const form = document.querySelector('.post-form');
                                    if(form){
                                        const tmp = document.createElement('button'); tmp.type='submit'; tmp.name='save'; tmp.style.display='none'; form.appendChild(tmp);

                                        // One-time htmx listener to detect the save response and then navigate
                                        let handled = false;
                                        function htmxHandler(evt){
                                            try{
                                                const xhr = evt.detail.xhr;
                                                const hxTrigger = xhr && xhr.getResponseHeader && xhr.getResponseHeader('HX-Trigger');
                                                if(hxTrigger && hxTrigger.indexOf('saved') !== -1){
                                                    handled = true;
                                                    if(window.htmx && typeof htmx.off === 'function') htmx.off('htmx:afterRequest', htmxHandler);
                                                    try{
                                                        const pageUrl = `{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=0 %}{% endif %}`.replace('/0/', '/' + destIndex + '/');
                                                        window.location = pageUrl;
                                                    }catch(e){
                                                        if(document.getElementById('goto-button')){
                                                            document.getElementById('goto-button').value = destIndex;
                                                            $('#goto-button').click();
                                                        }
                                                    }
                                                }
                                            }catch(e){/* ignore */}
                                        }

                                        if(window.htmx && typeof htmx.on === 'function'){
                                            htmx.on('htmx:afterRequest', htmxHandler);
                                        }

                                        // As a fallback listen for the custom 'saved' event
                                        const onSavedFallback = function(){ if(handled) return; handled = true; document.removeEventListener('saved', onSavedFallback); try{ const pageUrl = `{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=0 %}{% endif %}`.replace('/0/', '/' + destIndex + '/'); window.location = pageUrl; }catch(e){ if(document.getElementById('goto-button')){ document.getElementById('goto-button').value = destIndex; $('#goto-button').click(); } } };
                                        document.addEventListener('saved', onSavedFallback);

                                        tmp.click();

                                        // final timeout fallback
                                        setTimeout(function(){ if(!handled){ try{ document.removeEventListener('saved', onSavedFallback); if(window.htmx && typeof htmx.off === 'function') htmx.off('htmx:afterRequest', htmxHandler); const pageUrl = `{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=0 %}{% endif %}`.replace('/0/', '/' + destIndex + '/'); window.location = pageUrl; }catch(e){ try{ if(document.getElementById('goto-button')){ document.getElementById('goto-button').value = destIndex; $('#goto-button').click(); } }catch(e){} } } }, 1500);
                                        return;
                                    }
                                }

                                // skip or cancel -> load fragment directly via HTMX and update URL
                                try{
                                    const url = fragUrlTemplate.replace('/0/', '/' + destIndex + '/');
                                    if(window.htmx && typeof htmx.ajax === 'function'){
                                        htmx.ajax('GET', url, {target: '#question-fragment', swap: 'innerHTML'});
                                    } else {
                                        window.location.href = url;
                                    }
                                    try{
                                        const pageUrl = `{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=0 %}{% endif %}`.replace('/0/', '/' + destIndex + '/');
                                        history.replaceState(null, '', pageUrl);
                                    }catch(e){}
                                }catch(e){
                                    document.getElementById('goto-button').value = destIndex;
                                    $('#goto-button').click();
                                }
                            }).catch(function(){
                                // on error, fallback to navigation
                                document.getElementById('goto-button').value = destIndex;
                                $('#goto-button').click();
                            });
                            return;
                        }
                    }catch(ex){ console && console.error && console.error(ex); }

                    // Default: perform the form-based navigation (which will save)
                    document.getElementById('goto-button').value = destIndex;
                    $('#goto-button').click();
                });
            })();

            // Intercept Overview button to offer Save or Skip when all answers false
            (function(){
                const overview = document.getElementById('overview-button');
                if(!overview) return;
                const overviewUrl = `{% if cid %}{% url 'physics:exam_take_overview' pk=exam.pk cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_overview_user' pk=exam.pk %}{% endif %}`;
                overview.addEventListener('click', function(evt){
                    try{
                        const allFalse = Array.from(document.querySelectorAll('ol.physics-answer-list li')).every(li => {
                            const inp = li.querySelector('input');
                            return !(inp && inp.checked);
                        });
                        if(!allFalse) return; // allow normal submit (which will save)

                        // prevent the default submit while we prompt
                        evt.preventDefault(); evt.stopImmediatePropagation();
                        openSaveSkipModal('All answers are false. Save these answers or skip without saving?').then(function(choice){
                            if(choice === 'save'){
                                const form = document.querySelector('.post-form');
                                if(form){
                                    const tmp = document.createElement('button'); tmp.type='submit'; tmp.name='save'; tmp.style.display='none'; form.appendChild(tmp);
                                    const onSaved = function(){ document.removeEventListener('saved', onSaved); window.location = overviewUrl; };
                                    document.addEventListener('saved', onSaved);
                                    tmp.click();
                                    setTimeout(function(){ document.removeEventListener('saved', onSaved); window.location = overviewUrl; }, 1500);
                                    return;
                                }
                            }
                            // skip or cancel -> navigate without saving
                            window.location = overviewUrl;
                        }).catch(function(){ window.location = overviewUrl; });
                    }catch(ex){ console && console.error && console.error(ex); }
                });
            })();

            // Skip confirmation: if the user's current selections differ from
            // the saved answer, prompt before allowing the HTMX skip to proceed.
            (function(){
                const skip = document.getElementById('skip-button');
                if(!skip) return;

                // Build a JS array of saved answers (booleans) or null
                {% if saved_answer %}
                    const savedAnswers = [{% for s in saved_answer %}{{ s|yesno:"true,false" }}{% if not forloop.last %}, {% endif %}{% endfor %}];
                {% else %}
                    const savedAnswers = null;
                {% endif %}

                function readCurrent(){
                    const lis = document.querySelectorAll('ol.physics-answer-list li');
                    return Array.from(lis).map(li => {
                        const inp = li.querySelector('input');
                        return !!(inp && inp.checked);
                    });
                }

                skip.addEventListener('click', function(evt){
                    try{
                        const current = readCurrent();
                        let changed = false;
                        if(savedAnswers === null){
                            // no previously-saved answer; any current selection is a change
                            changed = current.some(Boolean);
                        } else {
                            if(current.length === savedAnswers.length){
                                for(let i=0;i<current.length;i++){
                                    if(!!current[i] !== !!savedAnswers[i]){ changed = true; break; }
                                }
                            } else {
                                // differing lengths — consider changed if any selection present
                                changed = current.some(Boolean);
                            }
                        }

                        if(changed){
                            evt.preventDefault(); evt.stopImmediatePropagation();
                            openSaveSkipModal('You have unsaved changes. Skip to the next question without saving?').then(function(choice){
                                if(choice === 'skip'){
                                    // trigger the HTMX GET on the button by invoking its click handler programmatically
                                    const hxGet = skip.getAttribute('hx-get');
                                    if(hxGet){
                                        if(window.htmx && typeof htmx.ajax === 'function'){
                                            htmx.ajax('GET', hxGet, {target: '#question-fragment', swap: 'innerHTML'});
                                        } else {
                                            window.location.href = hxGet;
                                        }
                                    }
                                } else if(choice === 'save'){
                                    const form = document.querySelector('.post-form');
                                    if(form){
                                        const tmp = document.createElement('button'); tmp.type='submit'; tmp.name='save'; tmp.style.display='none'; form.appendChild(tmp);
                                        tmp.click();
                                    }
                                }
                                // cancel => do nothing
                            }).catch(function(){/* ignore */});
                            return false;
                        }
                        // allow the HTMX attribute on the button to proceed
                    }catch(e){ console && console.error && console.error(e); }
                });
            })();
        })();
    </script>
        <!-- Save / Skip Modal -->
    <div class="modal fade" id="saveSkipModal" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Confirm</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <p id="saveSkipModalMessage">Are you sure?</p>
                </div>
                <div class="modal-footer">
                    <button type="button" id="saveSkipModalSave" class="btn btn-primary">Save</button>
                    <button type="button" id="saveSkipModalSkip" class="btn btn-secondary">Skip</button>
                    <button type="button" id="saveSkipModalCancel" class="btn btn-link" data-bs-dismiss="modal">Cancel</button>
                </div>
            </div>
        </div>
    </div>

    <script>
                // Modal helper: returns a Promise resolved with 'save'|'skip'|'cancel'
        function openSaveSkipModal(message){
            return new Promise(function(resolve, reject){
                try{
                    let modalEl = document.getElementById('saveSkipModal');
                    if(!modalEl) return resolve('cancel');
                    modalEl.querySelector('#saveSkipModalMessage').textContent = message || '';
                    const bsModal = new bootstrap.Modal(modalEl, { backdrop: 'static' });

                    function cleanup(){
                        saveBtn.removeEventListener('click', onSave);
                        skipBtn.removeEventListener('click', onSkip);
                        cancelBtn.removeEventListener('click', onCancel);
                        modalEl.removeEventListener('hidden.bs.modal', onHidden);
                    }

                    function onSave(){ cleanup(); bsModal.hide(); resolve('save'); }
                    function onSkip(){ cleanup(); bsModal.hide(); resolve('skip'); }
                    function onCancel(){ cleanup(); bsModal.hide(); resolve('cancel'); }
                    function onHidden(){ cleanup(); resolve('cancel'); }

                    const saveBtn = modalEl.querySelector('#saveSkipModalSave');
                    const skipBtn = modalEl.querySelector('#saveSkipModalSkip');
                    const cancelBtn = modalEl.querySelector('#saveSkipModalCancel');

                    saveBtn.addEventListener('click', onSave);
                    skipBtn.addEventListener('click', onSkip);
                    cancelBtn.addEventListener('click', onCancel);
                    modalEl.addEventListener('hidden.bs.modal', onHidden);

                    bsModal.show();
                }catch(e){ reject(e); }
            });
        }
    </script>
</div>
