{% extends 'atlas/base.html' %}
{% load crispy_forms_tags %}
{% load django_htmx %}

{% block content %}
    <div class="mb-2"><small class="text-muted">Collection: <strong>{{collection}}</strong></small></div>

    {% if viewing_as_user %}
    <div class="alert alert-info d-flex align-items-center gap-2 py-2 px-3 mb-3" role="alert">
        <i class="bi bi-eye-fill me-1"></i>
        <span><strong>Reviewer mode</strong> &mdash; Viewing <strong>{{ target_user.get_full_name|default:target_user.username }}</strong>&rsquo;s answers. This screen is read-only.</span>
        <a href="{% url 'atlas:collection_history_user' exam_id=collection.id user_pk=target_user.pk %}" class="btn btn-outline-info btn-sm ms-auto">Back to overview</a>
    </div>
    {% endif %}

    <div class="d-flex justify-content-between align-items-start mb-3">
        <div>
            <h2 class="h4 mb-0">Case {{case_number|add:1}}

                {% if show_title %}
                    : {{case.title}}
                {% endif %}


                {% if question_completed %}
                    <span class="badge bg-warning text-dark ms-2 small">REVIEW</span>
                {% endif %}

            </h2>
        </div>

        <div class="d-flex align-items-center ms-3">
            <div class="dropdown">
                <a class="btn btn-outline-secondary btn-sm dropdown-toggle" href="#" role="button" id="caseJump" data-bs-toggle="dropdown" aria-expanded="false"
                   hx-get="{% url 'atlas:collection_case_jump_partial' pk=collection.pk %}?current={{case_number}}{% if cid %}&cid={{cid}}&passcode={{passcode}}{% endif %}"
                   hx-target="#case-jump-menu"
                   hx-swap="innerHTML"
                   hx-trigger="click">
                    Jump
                </a>
                <div class="dropdown-menu dropdown-menu-end" id="case-jump-menu">
                    <div class="px-3 py-2 text-muted">Loading...</div>
                </div>
            </div>
        </div>
    </div>

    {% if not question_completed and effective_question_time_limit is not None %}
        <div id="question-timer-block" class="mb-3" title="This case has a view time limit of {{ effective_question_time_limit }} seconds.">
            <div class="d-flex align-items-center gap-3">
                <div><strong>Case view:</strong> <span id="question-timer" aria-live="polite">&nbsp;</span></div>
                <div class="flex-max-320">
                    <div class="progress progress-compact-sm">
                        <div id="question-timer-progress-inner" class="progress-bar" role="progressbar" style="width:100%; background:var(--timer-color, #28a745);"></div>
                    </div>
                </div>
            </div>
            {% if effective_answer_entry_grace_period %}
                <div id="answer-window-info" class="small text-muted mt-1 {% if not case_view_locked or answer_entry_closed %}d-none{% endif %}">
                    Answer window remaining: <span id="answer-window-timer">{{ effective_answer_entry_grace_period }}s</span>
                </div>
            {% endif %}
            <div id="timer-htmx-target" style="display:none;"></div>
            <div id="autosubmit-toast-container" style="position:fixed; top:16px; right:16px; z-index:10500;"></div>
        </div>
    {% endif %}

    <div id="case-view-locked-alert" class="alert alert-warning small {% if not case_view_locked %}d-none{% endif %}">
        {% if answer_entry_closed %}
            Case view is locked and the answer window has closed.
        {% else %}
            Case view is now locked. You can continue entering your answer until the answer window closes.
        {% endif %}
    </div>

{% comment %}     <details>
        <summary class="opacity-50">Help <i class="bi bi-info-circle"></i></summary>
    </details> {% endcomment %}


    <div id="case-view-content" {% if case_view_locked %}style="display:none;"{% endif %}>
        {% if not question_completed %}
            {% if resources %}
                <h5 class="mt-3">Resources</h5>
                <ul class="list-group list-group-flush mb-3">
                    {% for caseresource in resources %}
                        <li class="list-group-item py-1 small">{{caseresource.resource.get_display}}</li>
                    {% endfor %}
                </ul>
            {% endif %}
        {% endif %}


        {% if show_description and case.description %}
            <div class="mb-3">
                <h6 class="mb-1">Description</h6>
                <p class="mb-0">{{case.description}}</p>
            </div>
        {% endif %}
        {% if show_history %}
            <div class="card mb-3">
                <div class="card-body p-2 d-flex justify-content-between align-items-start">
                    <div class="me-3 small text-muted">History: {{casedetail.get_history_pre|linebreaks}}</div>
                    {% if has_priors %}
                        <div class="ms-2">
                            <span title="This case has priors available for comparison" class="badge bg-secondary text-white rounded-pill small">Priors{% if prior_count %} ({{ prior_count }}){% endif %}</span>
                        </div>
                    {% endif %}
                </div>
            </div>
        {% endif %}

        {% if casedetail.learner_comment %}
            <div class="alert alert-info small">
                <strong>Collection note:</strong> {{ casedetail.learner_comment|linebreaks }}
            </div>
        {% endif %}

        {% if question_completed and casedetail.learner_review_comment %}
            <div class="alert alert-secondary small">
                <strong>Review note:</strong> {{ casedetail.learner_review_comment|linebreaks }}
            </div>
        {% endif %}

        {% if collection.show_ohif_viewer or collection.show_ohif_viewer_link or collection.show_built_in_viewer %}
            <div id="viewer-panel" class="mb-3">
                {% if collection.show_built_in_viewer %}
                    <div class="d-flex align-items-center gap-2 py-1 px-2 mb-1 rounded bg-body-secondary">
                        <span class="text-muted fw-semibold small me-auto">Viewer</span>
                        <button type="button" class="btn btn-sm btn-outline-secondary py-0 px-2" id="viewer-sidebar-btn" title="Move viewer to sidebar">
                            <i class="bi bi-layout-sidebar-reverse"></i> <span class="d-none d-sm-inline">Sidebar</span>
                        </button>
                        <button type="button" class="btn btn-sm btn-outline-secondary py-0 px-2" id="viewer-popout-btn" title="Open viewer in a separate window">
                            <i class="bi bi-box-arrow-up-right"></i> <span class="d-none d-sm-inline">Pop&nbsp;out</span>
                        </button>
                    </div>
                    <div id="viewer-moveable-home">
                        <div id="viewer-moveable">
                            <div id="viewer-container" class="viewer-resizable-container">
                                 <div id="main_viewer" class="dicom-viewer-root viewer-frame-standard"
                                      data-auto-cache-stack="false"
                                      data-named-stacks='{{ named_stacks_json }}'
                                 ></div>
                            </div>
                            <div id="viewer-resize-handle" class="viewer-resize-handle" title="Drag to resize viewer">
                                <div class="viewer-resize-grip-inner"></div>
                            </div>
                        </div>
                    </div>
                {% endif %}

                {% if collection.show_ohif_viewer %}
                    <div{% if collection.show_built_in_viewer %} class="mt-3"{% endif %}>
                        {% if question_completed %}
                            <iframe id="viewer" class="viewer-frame-ohif" src="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% if case_number %}{% url 'atlas:collection_case_dicom_json_review' collection.pk case_number %}{% else %}{% url 'atlas:collection_case_dicom_json_review_legacy' collection.pk case.pk %}{% endif %}"></iframe>
                        {% else %}
                            <iframe id="viewer" class="viewer-frame-ohif" src="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% if case_number %}{% url 'atlas:collection_case_dicom_json' collection.pk case_number %}{% else %}{% url 'atlas:collection_case_dicom_json_legacy' collection.pk case.pk %}{% endif %}"></iframe>
                        {% endif %}
                    </div>
                {% endif %}

                {% if collection.show_ohif_viewer_link %}
                    <div class="mt-2">
                        {% if question_completed %}
                            <a target="_blank" href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% if case_number %}{% url 'atlas:collection_case_dicom_json_review' collection.pk case_number %}{% else %}{% url 'atlas:collection_case_dicom_json_review_legacy' collection.pk case.pk %}{% endif %}" title="Click to open the case in the advanced viewer. This will open in a new tab/window."><button class="viewer"><i class="bi bi-collection"></i> Launch advanced viewer.</button></a>
                        {% else %}
                            <a target="_blank" href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% if case_number %}{% url 'atlas:collection_case_dicom_json' collection.pk case_number %}{% else %}{% url 'atlas:collection_case_dicom_json_legacy' collection.pk case.pk %}{% endif %}" title="Click to open the case in the advanced viewer. This will open in a new tab/window."><button class="viewer"><i class="bi bi-collection"></i> Launch advanced viewer.</button></a>
                        {% endif %}
                    </div>
                {% endif %}
            </div>
        {% endif %}


{% comment %}         <div class="pre-whitespace multi-image-block">
            <details open>
                <summary>
                    Images
                </summary>
                {% for series, prior, relation in series_to_load %}
                    <span class="series-block
                                 {% if prior %}
                                     prior
                                 {% endif %}
                                ">
                        <a href="#" onclick='window.loadDicomViewer(window.images[{{forloop.counter0}}])'>
                            <span>
                                <span class="series-block-series-number">Series {{ forloop.counter }}:</span>
                                {{series.get_block}}
                            </span>
                            {% if prior %}
                                <br/><span class="relation">Prior: {{relation}}</span>
                            {% endif %}

                        </a>
                    </span>
                {% endfor %}
            </details>
        </div>

        <div>
            <div id="single-dicom-viewer" class="dicom-viewer" data-images="" data-annotations=''>
            </div>

        </div> {% endcomment %}

        {% if show_discussion and case.discussion %}
            <details class="card mb-3">
                <summary class="card-header p-2" style="cursor: pointer;">
                    <strong>Discussion</strong>
                </summary>
                <div class="card-body p-2 small">
                    {{case.discussion|linebreaks}}
                </div>
            </details>
        {% endif %}
        {% if show_report and case.report %}
            <details class="card mb-3">
                <summary class="card-header p-2" style="cursor: pointer;">
                    <strong>Report</strong>
                </summary>
                <div class="card-body p-2 small">
                    {{case.report|linebreaks}}
                </div>
            </details>
        {% endif %}
    </div>

    {% if question_completed %}

        {% if collection.show_case_link_post %}
            <div class="mb-3">
                <a class="btn btn-outline-secondary btn-sm" target="_blank" href="{{ case.get_absolute_url }}">Open case</a>
            </div>
        {% endif %}

        {% if collection.show_findings_post %}
            {% include 'atlas/partials/_series_findings.html' %}
        {% endif %}
        {% if collection.show_displaysets_post %}
            {% include 'atlas/partials/_case_displaysets.html' %}
        {% endif %}
        {% if collection.show_differentials_post %}
            {% include 'atlas/partials/_case_differentials.html' %}
        {% endif %}

        {% if resources %}
            <h5>Resources</h4>
            <ul class="no-list-style">
                {% for caseresource in resources %}
                    <li>
                        {{caseresource.resource.get_display}}
                    </li>
                {% endfor %}
            </ul>
        {% endif %}

    {% endif %}
    <form method="POST" class="post-form{% if question_completed %} completed{% endif %}">{% csrf_token %}
        {% if collection.collection_type == "QUE" %}
            {% if question_completed %}
                <h3>Answers</h3>
                {% include "atlas/partials/collection_question_answer_block.html" %}

                {% if collection.self_review %}
                    <div id="self-review-panel-que">
                        {% include 'atlas/partials/_self_review_block.html' with panel_key='que' %}
                    </div>
                {% else %}
                    <h4>Answer score: {{answer.score}}</h4>
                    Answer feedback: {{answer.feedback|safe}}
                    <br/>
                {% endif %}

                <details><summary class="opacity-50">View questions</summary>
                    {{form.json.errors}}
                    <div class="form-contents">
                        <fieldset {% if question_completed %}disabled="disabled"{% endif %}>
                            {{form}}
                        </fieldset>
                    </div>
                </details>

            {% else %}

                {{form.json.errors}}
                <div class="form-contents">
                    <fieldset {% if question_completed or answer_entry_closed %}disabled="disabled"{% endif %}>
                        {{form}}
                    </fieldset>
                </div>

            {% endif %}

        {% elif collection.collection_type == "REP" %}
            {{form.json.errors}}
            <div class="form-contents">
                <fieldset {% if question_completed or answer_entry_closed %}disabled="disabled"{% endif %}>
                    {{form | crispy}}
                </fieldset>
            </div>

            {% if question_completed %}
                <div>
                    {% if collection.self_review %}
                        <div id="self-review-panel-rep">
                            {% include 'atlas/partials/_self_review_block.html' with panel_key='rep' %}
                        </div>
                    {% else %}
                        <h4>Answer score: {{answer.score}}</h4>
                        Answer feedback: {{answer.feedback|safe}}
                        <br/>
                    {% endif %}
                </div>
            {% endif %}

        {% endif %}
        {% if not viewing_as_user %}
        <div class="mb-2">
            {% if previous %}
                <button type="submit" name="previous" class="btn btn-outline-secondary btn-sm me-2">Previous</button>
            {% endif %}
            {% if next %}
                <button type="submit" name="next" class="btn btn-primary btn-sm me-2">Next</button>
            {% elif collection.collection_type == "REP" %}
                {% if not exam.publish_results %}
                    <button type="submit" name="save" class="btn btn-primary btn-sm me-2">Save</button>
                {% endif %}
            {% endif %}
        </div>

        {% if collection.self_review and not collection.feedback_once_collection_complete and not question_completed %}
            <button type="submit" name="complete_case" class="btn btn-success btn-sm">Finish Case</button>
        {% endif %}

        <div class="mt-3">
            <button type="submit" name="finish" class="btn btn-outline-secondary btn-sm">Overview</button>
            <button type="submit" id="goto-button" value="test" name="goto" class="hide">goto</button>
        </div>
        {% else %}
        {# Read-only navigation for reviewer mode — uses anchor links to avoid mutating POST #}
        <div class="mb-2 d-flex gap-2 flex-wrap">
            {% if previous %}
                <a href="{% url 'atlas:collection_case_view_take_review_user' pk=collection.id case_number=case_number|add:'-1' user_pk=target_user.pk %}" class="btn btn-outline-secondary btn-sm">Previous</a>
            {% endif %}
            {% if next %}
                <a href="{% url 'atlas:collection_case_view_take_review_user' pk=collection.id case_number=case_number|add:'1' user_pk=target_user.pk %}" class="btn btn-primary btn-sm">Next</a>
            {% endif %}
        </div>
        <div class="mt-3">
            <a href="{% url 'atlas:collection_history_user' exam_id=collection.id user_pk=target_user.pk %}" class="btn btn-outline-secondary btn-sm">Overview</a>
        </div>
        {% endif %}
    </form>

    {% if question_completed and collection.case_query_messaging_enabled %}
        <details class="mt-3" {% if case_review_stats.has_outstanding_any %}open{% endif %}>
            <summary class="small fw-semibold d-flex flex-wrap align-items-center gap-2">
                <span>Case conversation</span>
                {% if case_review_stats.has_outstanding_any %}
                    <span class="badge bg-danger">{{ case_review_stats.outstanding_total_count }} unacknowledged message{{ case_review_stats.outstanding_total_count|pluralize }}</span>
                {% elif case_review_stats.has_messages %}
                    <span class="badge bg-secondary">{{ case_review_stats.message_count }} message{{ case_review_stats.message_count|pluralize }}</span>
                {% else %}
                    <span class="text-muted">No messages yet</span>
                {% endif %}
            </summary>
            <div class="mt-2"
                 hx-get="{% url 'atlas:collection_case_review_thread' exam_id=collection.id cid_user_exam_id=cid_user_exam.id case_id=case.id %}{% if cid %}?cid={{ cid }}&passcode={{ passcode }}{% endif %}"
                 hx-trigger="load"
                 hx-target="this"
                 hx-swap="innerHTML">
                <div class="small text-muted">Loading case conversation...</div>
            </div>
        </details>
    {% endif %}

    <aside id="selfReviewSidebar" class="self-review-sidebar" aria-live="polite" aria-label="Self review sidebar">
        <div class="self-review-sidebar-header">
            <h5 class="mb-0" id="selfReviewSidebarLabel">Self Review</h5>
            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="closeSelfReviewSidebar()">Close</button>
        </div>
        <div id="selfReviewSidebarBody" class="self-review-sidebar-body">
            <div class="p-3 text-muted small">Choose Sidebar to load the self-review form here.</div>
        </div>
    </aside>

    <aside id="viewerSidebar" class="viewer-sidebar" aria-label="Viewer sidebar">
        <div id="viewer-sidebar-resize-handle" class="viewer-sidebar-resize-handle" title="Drag to resize sidebar" aria-hidden="true"></div>
        <div class="viewer-sidebar-header">
            <span class="fw-semibold">Viewer</span>
            <button type="button" class="btn btn-sm btn-outline-secondary" id="viewer-sidebar-close-btn">Close</button>
        </div>
        <div id="viewerSidebarBody" class="viewer-sidebar-body"></div>
    </aside>

    <style>
        label {
            vertical-align: top;

        }
        .series-block {
            border: darkblue solid 1px;
            padding: 1px;
            text-decoration: none;
            text-align: center;
        }
        .series-block a {
            all: unset;
        }
        .series-block:hover {
            background-color: darkblue;
        }

        .series-block.prior {
            border: darkgray solid 1px;
        }

        fieldset:disabled textarea {
            background-color: black;
        }

        form.completed {
        }

        .correct {
        }

        .correct h4::after {
            content: '✓';
            color: green;
        }

        .incorrect h4::after {
            content: '✗';
            color: orange;
        }

        .incorrect.automark h4::after {
            content: '✗';
            color: red;
        }

        .answer-block>div {
            padding-top: 10px;
        }

        .relation {
            opacity: 0.5;
            font-size: 0.8em;
        }

        .viewer {
            background-color: darkblue;
            color: white;
            border: none;
            border-radius: 5px;
            padding: 5px;
            opacity: 0.4;
        }

        .viewer:hover {
            opacity: 1;
            background-color: darkblue;

        }

        .self-review-actions .btn {
            white-space: nowrap;
        }

        .self-review-sidebar {
            position: fixed;
            top: 0;
            right: 0;
            width: min(760px, 94vw);
            height: 100vh;
            background: var(--bs-body-bg);
            border-left: 1px solid var(--bs-border-color);
            box-shadow: -8px 0 18px rgba(0, 0, 0, 0.35);
            z-index: 1050;
            transform: translateX(100%);
            transition: transform 0.2s ease-in-out;
            display: flex;
            flex-direction: column;
        }

        .self-review-sidebar.open {
            transform: translateX(0);
        }

        .self-review-sidebar-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 0.75rem 1rem;
            border-bottom: 1px solid var(--bs-border-color);
            background: var(--bs-secondary-bg);
        }

        .self-review-sidebar-body {
            overflow: auto;
            flex: 1 1 auto;
        }

        .viewer-resizable-container {
            position: relative;
            overflow: hidden;
            height: clamp(560px, 78vh, 920px);
            min-height: 320px;
            max-height: 85vh;
            resize: vertical;
        }

        .viewer-resizable-container .dicom-viewer-root {
            width: 100% !important;
            height: 100% !important;
            min-height: 0;
            max-height: none !important;
        }

        #viewer-container {
            width: 100%;
        }

        #viewer-container #main_viewer {
            box-sizing: border-box;
        }

        @media (max-width: 991.98px) {
            .viewer-resizable-container {
                height: clamp(360px, 60vh, 640px);
                min-height: 280px;
            }
        }

        .viewer-resize-handle {
            height: 10px;
            background: var(--bs-secondary-bg);
            border: 1px solid var(--bs-border-color);
            border-top: none;
            border-radius: 0 0 4px 4px;
            cursor: ns-resize;
            display: flex;
            align-items: center;
            justify-content: center;
            user-select: none;
            touch-action: none;
            display: none;
        }

        .viewer-resize-handle:hover {
            background: var(--bs-tertiary-bg);
        }

        .viewer-resize-grip-inner {
            width: 40px;
            height: 3px;
            background: var(--bs-secondary-color);
            border-radius: 2px;
            opacity: 0.4;
        }

        .viewer-sidebar {
            position: fixed;
            top: 0;
            right: 0;
            width: min(850px, 95vw);
            min-width: 360px;
            max-width: 95vw;
            height: 100vh;
            background: var(--bs-body-bg);
            border-left: 1px solid var(--bs-border-color);
            box-shadow: -8px 0 18px rgba(0, 0, 0, 0.35);
            z-index: 1045;
            transform: translateX(100%);
            transition: transform 0.2s ease-in-out;
            display: flex;
            flex-direction: column;
            resize: horizontal;
            overflow: auto;
        }

        .viewer-sidebar-resize-handle {
            position: absolute;
            left: 0;
            top: 0;
            width: 10px;
            height: 100%;
            cursor: ew-resize;
            z-index: 3;
            background: linear-gradient(to right, rgba(100,181,246,0.28), rgba(100,181,246,0));
            touch-action: none;
        }

        .viewer-sidebar.open {
            transform: translateX(0);
        }

        .viewer-sidebar-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 0.5rem 1rem;
            border-bottom: 1px solid var(--bs-border-color);
            background: var(--bs-secondary-bg);
            flex-shrink: 0;
        }

        .viewer-sidebar-body {
            flex: 1 1 auto;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }

        .viewer-sidebar-body #viewer-moveable {
            flex: 1 1 auto;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }

        .viewer-sidebar-body #viewer-container {
            flex: 1 1 auto;
            height: auto !important;
        }

        .viewer-sidebar-body .viewer-resize-handle {
            display: none;
        }

        body.viewer-sidebar-open {
            margin-right: var(--viewer-sidebar-width, min(850px, 95vw));
            transition: margin-right 0.2s ease-in-out;
        }

        @media (max-width: 991.98px) {
            body.viewer-sidebar-open {
                margin-right: 0;
            }
        }
    </style>

{% endblock %}
{% block js %}
    {{ form.media }}
{% comment %} <script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js"></script> {% endcomment %}
    <script type="text/javascript">

        // Question time limit countdown + auto-submit
        $(function () {

            function lockCaseView() {
                var $view = $('#case-view-content');
                if ($view.length) {
                    $view.hide();
                }
                $('#case-view-locked-alert').removeClass('d-none');
                $('#answer-window-info').removeClass('d-none');
            }

            function closeAnswerWindow() {
                $('#answer-window-info').addClass('d-none');
                $('#case-view-locked-alert')
                    .removeClass('d-none')
                    .text('Case view is locked and the answer window has closed.');
            }

            function lockQuestion() {
                // Only disable save buttons to prevent further saves
                $form = $('form.post-form');
                var $saveBtns = $form.find('button[name="save"], #id_answer');
                if ($saveBtns.length) {
                    $saveBtns.prop('disabled', true);
                }

                // Visual feedback: set timer to Locked and progress to red
                $progressInner = $('#question-timer-progress-inner');
                $('#question-timer').text('Locked');
                $progressInner.css('background', '#dc3545');
                $progressInner.css('width', '0%');
                closeAnswerWindow();

                $("#question-timer-progress-outer").hide();
            }

            try {
                var timeLimit = {{ effective_question_time_limit|default:'null' }};
                var answerGrace = {{ effective_answer_entry_grace_period|default:'0' }};
                var questionCompleted = {{ question_completed|yesno:"true,false" }};
                var answerStartedAtIso = "{{ answer_started_at_iso|default:'null' }}";
                console.debug('Timer init:', {timeLimit: timeLimit, answerGrace: answerGrace, questionCompleted: questionCompleted});

                if (!timeLimit || questionCompleted) {
                    return;
                }

                {% if answer %}
                    if ({{answer.completed|yesno:"true,false"}}) {
                        lockQuestion();
                        console.debug('Timer: answer already completed, aborting timer init');
                        return;
                    }
                {% endif %}

                var $timer = $('#question-timer');
                var $form = $('form.post-form');

                if ($timer.length === 0 || $form.length === 0) {
                    console.debug('Timer: required elements not found, aborting timer init');
                    return;
                }

                // Compute remaining values based on the canonical start time (if provided)
                var remainingToLock = parseInt(timeLimit, 10);
                var remainingToClose = parseInt(timeLimit, 10) + parseInt(answerGrace || 0, 10);
                if (answerStartedAtIso) {
                    try {
                        var started = new Date(answerStartedAtIso);
                        var now = new Date();
                        var elapsed = Math.floor((now - started) / 1000);
                        remainingToLock = Math.max(0, remainingToLock - elapsed);
                        remainingToClose = Math.max(0, remainingToClose - elapsed);
                        console.debug('Timer: using started_at, elapsed seconds:', elapsed, 'remainingToLock:', remainingToLock, 'remainingToClose:', remainingToClose);
                    } catch (e) {
                        console.debug('Timer: invalid started_at iso, falling back to full timeLimit', e);
                    }
                }

                // If case-view time has elapsed on load, hide case content.
                if (remainingToLock <= 0) {
                    lockCaseView();
                }

                // If answer-entry time has elapsed on load, fully lock.
                if (remainingToClose <= 0) {
                    console.debug('Timer: answer-entry window already expired on load, locking without autosubmit');
                    lockQuestion();
                    $timer.text('Locked');
                    return;
                }

                function formatTime(s) {
                    var mins = Math.floor(s / 60);
                    var secs = s % 60;
                    return mins + ':' + (secs < 10 ? '0' + secs : secs);
                }

                var $progressInner = $('#question-timer-progress-inner');
                $timer.text(remainingToLock > 0 ? formatTime(remainingToLock) : 'Locked');
                if ($('#answer-window-timer').length && remainingToLock <= 0 && remainingToClose > 0) {
                    $('#answer-window-info').removeClass('d-none');
                    $('#answer-window-timer').text(formatTime(remainingToClose));
                } else if ($('#answer-window-timer').length) {
                    $('#answer-window-info').addClass('d-none');
                }

                function updateProgress() {
                    var pct = Math.max(0, Math.min(100, Math.round((remainingToLock / timeLimit) * 100)));
                    var widthPct = pct;
                    $progressInner.css('width', widthPct + '%');

                    // Smooth color transition: green (120) -> orange (30) -> red (0)
                    // We use a two-stage interpolation so the midpoint (~50%) is orange.
                    var hue = 0;
                    if (pct > 50) {
                        // interpolate from orange (30) to green (120)
                        var t = (pct - 50) / 50.0; // 0..1
                        hue = 30 + t * (120 - 30);
                    } else {
                        // interpolate from red (0) to orange (30)
                        var t = pct / 50.0; // 0..1
                        hue = 0 + t * (30 - 0);
                    }

                    var color = 'hsl(' + Math.round(hue) + ', 75%, 40%)';
                    $progressInner.css('background', color);
                }

                updateProgress();

                var intervalId = setInterval(function () {
                    remainingToLock -= 1;
                    remainingToClose -= 1;

                    if (remainingToLock <= 0) {
                        lockCaseView();
                        $timer.text('Locked');
                        $progressInner.css('width', '0%');
                        $progressInner.css('background', '#dc3545');
                    } else {
                        $timer.text(formatTime(remainingToLock));
                        updateProgress();
                    }

                    if ($('#answer-window-timer').length) {
                        if (remainingToLock <= 0 && remainingToClose > 0) {
                            $('#answer-window-info').removeClass('d-none');
                            $('#answer-window-timer').text(formatTime(Math.max(0, remainingToClose)));
                        } else {
                            $('#answer-window-info').addClass('d-none');
                        }
                    }

                    if (remainingToClose <= 0) {
                        clearInterval(intervalId);
                        $timer.text('Locked');
                        $progressInner.css('width', '0%');
                        $progressInner.css('background', '#dc3545');
                        //var $next = $form.find('button[name="next"]');
                        //var $finish = $form.find('button[name="finish"]');

                        // Instead of navigating away, submit via fetch with timed_out flag
                        // Use HTMX to POST the timed_out flag and then lock the UI

                        var onAfter = function (evt) {
                            try {
                                var resp = null;
                                try {
                                    var xhr = evt && evt.detail && evt.detail.xhr;
                                    if (xhr && xhr.responseText) {
                                        resp = JSON.parse(xhr.responseText);
                                    }
                                } catch (e) {
                                    console.debug('No JSON response from timed_out request', e);
                                }

                                lockQuestion();

                                var msg = 'Answer auto-submitted';
                                if (resp && resp.submitted_at) {
                                    try {
                                        var dt = new Date(resp.submitted_at);
                                        msg += ' at ' + dt.toLocaleTimeString();
                                    } catch (e) {}
                                }
                                toastr.info(msg);
                            } catch (e) {
                                console.error('Error handling timed_out htmx response', e);
                            } finally {
                                htmx.off('htmx:afterRequest', onAfter);
                            }
                        };

                        htmx.on('htmx:afterRequest', onAfter);
                        // Serialize the entire form so the server receives the user's answers
                        // along with the timed_out flag. This ensures the form.save() path
                        // can validate and persist the submitted answers on timeout.
                        (function(){
                            var formValues = {};
                            try {
                                $.each($form.serializeArray(), function(i, field) {
                                    if (formValues[field.name] !== undefined) {
                                        if (!Array.isArray(formValues[field.name])) {
                                            formValues[field.name] = [formValues[field.name]];
                                        }
                                        formValues[field.name].push(field.value);
                                    } else {
                                        formValues[field.name] = field.value;
                                    }
                                });
                            } catch (e) {
                                console.debug('Failed to serialize form with jQuery, falling back to manual collection', e);
                                // Fallback: try to collect inputs manually
                                var inputs = $form.find('input, textarea, select').not(':disabled');
                                inputs.each(function () {
                                    var $el = $(this);
                                    var name = $el.attr('name');
                                    if (!name) return;
                                    var val = $el.val();
                                    if (formValues[name] !== undefined) {
                                        if (!Array.isArray(formValues[name])) {
                                            formValues[name] = [formValues[name]];
                                        }
                                        formValues[name].push(val);
                                    } else {
                                        formValues[name] = val;
                                    }
                                });
                            }

                            // Ensure the timed_out flag is included
                            formValues['timed_out'] = '1';

                            htmx.ajax('POST', window.location.href, {
                                values: formValues,
                                swap: 'none',
                                headers: {
                                    'X-CSRFToken': document.querySelector('input[name="csrfmiddlewaretoken"]').value,
                                },
                                target: "#timer-htmx-target",
                            });
                        })();
                    }
                }, 1000);

                $form.on('submit', function () {
                    clearInterval(intervalId);
                });
            } catch (e) {
                console.error('Error initializing timer:', e);
            }
        });

        window.openSelfReviewPopup = function (url) {
            var popupUrl = url + (url.indexOf('?') === -1 ? '?popup=1' : '&popup=1');
            var features = 'width=980,height=840,resizable=yes,scrollbars=yes';
            window.open(popupUrl, 'selfReviewPopup', features);
        };

        window.selfReviewCurrentEmbedUrl = null;

        window.refreshSelfReviewPanels = async function () {
            try {
                var resp = await fetch(window.location.href, { credentials: 'same-origin' });
                var html = await resp.text();
                var parser = new DOMParser();
                var doc = parser.parseFromString(html, 'text/html');

                var currentPanels = document.querySelectorAll('.js-self-review-panel[data-refresh-key]');
                currentPanels.forEach(function (currentPanel) {
                    var key = currentPanel.getAttribute('data-refresh-key');
                    if (!key) return;
                    var replacement = doc.querySelector('.js-self-review-panel[data-refresh-key="' + key + '"]');
                    if (replacement) {
                        currentPanel.outerHTML = replacement.outerHTML;
                    }
                });
            } catch (e) {
                console.warn('Unable to refresh self review panels', e);
            }
        };

        window.addEventListener('message', function (event) {
            if (!event || !event.data) return;
            if (event.data.type === 'self_review_saved') {
                window.refreshSelfReviewPanels();
            }
        });

        window.bindSelfReviewEmbedForm = function () {
            var root = document.getElementById('selfReviewSidebarBody');
            if (!root) return;

            var form = root.querySelector('form.self-review-embed-form');
            if (!form) return;

            if (form.dataset.bound === '1') return;
            form.dataset.bound = '1';

            form.addEventListener('submit', async function (event) {
                event.preventDefault();

                var formData = new FormData(form);
                var csrftokenInput = form.querySelector('input[name="csrfmiddlewaretoken"]');
                var csrftoken = csrftokenInput ? csrftokenInput.value : '';

                try {
                    var resp = await fetch(window.selfReviewCurrentEmbedUrl || window.location.href, {
                        method: 'POST',
                        body: formData,
                        headers: {
                            'X-Requested-With': 'XMLHttpRequest',
                            'X-CSRFToken': csrftoken,
                        },
                        credentials: 'same-origin',
                    });

                    if (resp.redirected) {
                        root.innerHTML = '<div class="p-3"><div class="alert alert-success mb-0">Self review saved. You can continue reviewing this case.</div></div>';
                        setTimeout(function () {
                            window.closeSelfReviewSidebar();
                            window.refreshSelfReviewPanels();
                        }, 500);
                        return;
                    }

                    var html = await resp.text();
                    root.innerHTML = html;
                    window.bindSelfReviewEmbedForm();
                } catch (e) {
                    var msg = root.querySelector('.self-review-embed-message');
                    if (msg) {
                        msg.innerHTML = '<div class="alert alert-danger py-2">Unable to save self review. Please try again.</div>';
                    }
                }
            });
        };

        window.closeSelfReviewSidebar = function () {
            var sidebar = document.getElementById('selfReviewSidebar');
            if (sidebar) {
                sidebar.classList.remove('open');
            }
        };

        window.openSelfReviewSidebar = async function (url) {
            var sidebar = document.getElementById('selfReviewSidebar');
            var body = document.getElementById('selfReviewSidebarBody');
            if (!sidebar || !body) {
                window.location.href = url;
                return;
            }

            var embedUrl = url + (url.indexOf('?') === -1 ? '?embed=1' : '&embed=1');
            window.selfReviewCurrentEmbedUrl = embedUrl;
            body.innerHTML = '<div class="p-3 text-muted small">Loading self-review form...</div>';
            sidebar.classList.add('open');

            try {
                var resp = await fetch(embedUrl, { credentials: 'same-origin' });
                var html = await resp.text();
                body.innerHTML = html;
                window.bindSelfReviewEmbedForm();
            } catch (e) {
                body.innerHTML = '<div class="p-3"><div class="alert alert-danger py-2 mb-0">Could not load self-review sidebar content. Use Popup as fallback.</div></div>';
            }
        };

    </script>

    <script type="text/javascript">
        (function () {
            function initViewerControls() {
                var COLL_PK = '{{ collection.pk }}';
                var HEIGHT_KEY = 'rad_viewer_h_' + COLL_PK;
                var MODE_KEY = 'rad_viewer_mode_' + COLL_PK;
                var POPOUT_STATE_KEY = 'rad_local_viewer_popout_state';
                var SIDEBAR_W_KEY = 'rad_viewer_w_' + COLL_PK;

                var panel = document.getElementById('viewer-panel');
                var moveableHome = document.getElementById('viewer-moveable-home');
                var moveable = document.getElementById('viewer-moveable');
                var container = document.getElementById('viewer-container');
                var resizeHandle = document.getElementById('viewer-resize-handle');
                var sidebarEl = document.getElementById('viewerSidebar');
                var sidebarBody = document.getElementById('viewerSidebarBody');
                var sidebarBtn = document.getElementById('viewer-sidebar-btn');
                var sidebarCloseBtn = document.getElementById('viewer-sidebar-close-btn');
                var sidebarResizeHandle = document.getElementById('viewer-sidebar-resize-handle');
                var popoutBtn = document.getElementById('viewer-popout-btn');
                var mainViewerEl = document.getElementById('main_viewer');
                var rootStyle = document.documentElement.style;

                if (!panel || !moveableHome || !moveable || !container || !mainViewerEl) {
                    return;
                }

                if (panel.dataset.viewerControlsBound === '1') {
                    return;
                }
                panel.dataset.viewerControlsBound = '1';


                var savedH = localStorage.getItem(HEIGHT_KEY);
                if (savedH && !isNaN(parseInt(savedH, 10))) {
                    container.style.height = parseInt(savedH, 10) + 'px';
                }

                function applySidebarWidth(px) {
                    if (!sidebarEl || !px || isNaN(px)) return;
                    var clamped = Math.max(360, Math.min(window.innerWidth * 0.95, Math.round(px)));
                    sidebarEl.style.width = clamped + 'px';
                    rootStyle.setProperty('--viewer-sidebar-width', clamped + 'px');
                }

                var savedW = localStorage.getItem(SIDEBAR_W_KEY);
                if (savedW && !isNaN(parseInt(savedW, 10))) {
                    applySidebarWidth(parseInt(savedW, 10));
                } else if (sidebarEl) {
                    rootStyle.setProperty('--viewer-sidebar-width', Math.round(sidebarEl.getBoundingClientRect().width) + 'px');
                }

                if (sidebarEl && 'ResizeObserver' in window) {
                    var sidebarResizeObserver = new ResizeObserver(function () {
                        var width = Math.round(sidebarEl.getBoundingClientRect().width);
                        rootStyle.setProperty('--viewer-sidebar-width', width + 'px');
                        localStorage.setItem(SIDEBAR_W_KEY, width);
                    });
                    sidebarResizeObserver.observe(sidebarEl);
                }

                if (sidebarResizeHandle && sidebarEl) {
                    var sidebarResizing = false;
                    var sidebarStartX = 0;
                    var sidebarStartWidth = 0;

                    var onSidebarPointerMove = function (event) {
                        if (!sidebarResizing) return;
                        var delta = sidebarStartX - event.clientX;
                        var nextWidth = sidebarStartWidth + delta;
                        applySidebarWidth(nextWidth);
                    };

                    var stopSidebarResize = function () {
                        if (!sidebarResizing) return;
                        sidebarResizing = false;
                        document.body.style.cursor = '';
                        document.body.style.userSelect = '';
                        var width = Math.round(sidebarEl.getBoundingClientRect().width);
                        localStorage.setItem(SIDEBAR_W_KEY, width);
                    };

                    sidebarResizeHandle.addEventListener('pointerdown', function (event) {
                        event.preventDefault();
                        sidebarResizing = true;
                        sidebarStartX = event.clientX;
                        sidebarStartWidth = sidebarEl.getBoundingClientRect().width;
                        document.body.style.cursor = 'ew-resize';
                        document.body.style.userSelect = 'none';
                    });

                    window.addEventListener('pointermove', onSidebarPointerMove);
                    window.addEventListener('pointerup', stopSidebarResize);
                    window.addEventListener('pointercancel', stopSidebarResize);
                }

                var persistHeight = function () {
                    localStorage.setItem(HEIGHT_KEY, Math.round(container.getBoundingClientRect().height));
                };

                if ('ResizeObserver' in window) {
                    var ro = new ResizeObserver(function () {
                        persistHeight();
                    });
                    ro.observe(container);
                } else {
                    window.addEventListener('mouseup', persistHeight);
                }

                if (resizeHandle) {
                    resizeHandle.addEventListener('pointerdown', function (e) {
                        e.preventDefault();
                    });
                }

                function openViewerSidebar() {
                    if (!sidebarEl || !sidebarBody) return;
                    sidebarBody.appendChild(moveable);
                    sidebarEl.classList.add('open');
                    document.body.classList.add('viewer-sidebar-open');
                    rootStyle.setProperty('--viewer-sidebar-width', Math.round(sidebarEl.getBoundingClientRect().width) + 'px');
                    if (sidebarBtn) {
                        sidebarBtn.innerHTML = '<i class="bi bi-x-lg"></i> <span class="d-none d-sm-inline">Close sidebar</span>';
                        sidebarBtn.classList.replace('btn-outline-secondary', 'btn-secondary');
                    }
                    localStorage.setItem(MODE_KEY, 'sidebar');
                }

                function closeViewerSidebar() {
                    if (!sidebarEl) return;
                    moveableHome.appendChild(moveable);
                    sidebarEl.classList.remove('open');
                    document.body.classList.remove('viewer-sidebar-open');
                    if (sidebarBtn) {
                        sidebarBtn.innerHTML = '<i class="bi bi-layout-sidebar-reverse"></i> <span class="d-none d-sm-inline">Sidebar</span>';
                        sidebarBtn.classList.replace('btn-secondary', 'btn-outline-secondary');
                    }
                    localStorage.removeItem(MODE_KEY);
                }

                if (sidebarBtn) {
                    sidebarBtn.addEventListener('click', function () {
                        if (sidebarEl && sidebarEl.classList.contains('open')) {
                            closeViewerSidebar();
                        } else {
                            openViewerSidebar();
                        }
                    });
                }

                if (sidebarCloseBtn) {
                    sidebarCloseBtn.addEventListener('click', closeViewerSidebar);
                }

                var bc = null;
                try { bc = new BroadcastChannel('viva_load'); } catch (e) {}

                function getViewerPayload() {
                    var namedStacks = mainViewerEl.getAttribute('data-named-stacks');
                    var images = mainViewerEl.getAttribute('data-images');
                    var viewerState = window.exportViewerState_main_viewer ? window.exportViewerState_main_viewer() : '';
                    var annotations = window.exportAnnotations_main_viewer ? window.exportAnnotations_main_viewer() : '';

                    return {
                        type: 'open',
                        namedStacks: namedStacks || '',
                        images: images || '',
                        viewerstate: viewerState || '',
                        annotations: annotations || ''
                    };
                }

                function broadcastViewerState(payload) {
                    if (!payload) return;
                    localStorage.setItem(POPOUT_STATE_KEY, JSON.stringify(payload));
                    if (bc) {
                        try { bc.postMessage(payload); } catch (e) {}
                    }
                }

                function showPopoutPlaceholder() {
                    var existing = panel.querySelector('.viewer-popout-placeholder');
                    if (existing) return;
                    var placeholder = document.createElement('div');
                    placeholder.className = 'alert alert-secondary small py-2 mb-0 mt-1 d-flex align-items-center gap-2 viewer-popout-placeholder';
                    placeholder.innerHTML = '<i class="bi bi-box-arrow-up-right"></i> Viewer is open in a separate window. <button type="button" class="btn btn-sm btn-outline-secondary ms-auto" id="viewer-popout-bring-back">Bring back</button>';
                    panel.insertBefore(placeholder, moveableHome);
                    moveableHome.style.display = 'none';
                    document.getElementById('viewer-popout-bring-back').addEventListener('click', closePopout);
                }

                function hidePopoutPlaceholder() {
                    var placeholder = panel.querySelector('.viewer-popout-placeholder');
                    if (placeholder) placeholder.remove();
                    moveableHome.style.display = '';
                }

                function openPopout() {
                    if (sidebarEl && sidebarEl.classList.contains('open')) {
                        closeViewerSidebar();
                    }
                    var payload = getViewerPayload();
                    broadcastViewerState(payload);
                    window.open('{% url "atlas:collection_viewer_local" %}', 'collectionTakeViewer', 'width=1200,height=900,noopener');
                    setTimeout(function () { broadcastViewerState(payload); }, 700);
                    localStorage.setItem(MODE_KEY, 'popout');
                    showPopoutPlaceholder();
                    if (popoutBtn) {
                        popoutBtn.innerHTML = '<i class="bi bi-x-lg"></i> <span class="d-none d-sm-inline">Bring back</span>';
                        popoutBtn.classList.replace('btn-outline-secondary', 'btn-secondary');
                    }
                }

                function closePopout() {
                    hidePopoutPlaceholder();
                    localStorage.removeItem(MODE_KEY);
                    if (popoutBtn) {
                        popoutBtn.innerHTML = '<i class="bi bi-box-arrow-up-right"></i> <span class="d-none d-sm-inline">Pop&nbsp;out</span>';
                        popoutBtn.classList.replace('btn-secondary', 'btn-outline-secondary');
                    }
                }

                if (popoutBtn) {
                    popoutBtn.addEventListener('click', function () {
                        if (localStorage.getItem(MODE_KEY) === 'popout') {
                            closePopout();
                        } else {
                            openPopout();
                        }
                    });
                }

                var savedMode = localStorage.getItem(MODE_KEY);
                if (savedMode === 'sidebar') {
                    openViewerSidebar();
                } else if (savedMode === 'popout' && popoutBtn) {
                    showPopoutPlaceholder();
                    setTimeout(function () { broadcastViewerState(getViewerPayload()); }, 300);
                    popoutBtn.innerHTML = '<i class="bi bi-x-lg"></i> <span class="d-none d-sm-inline">Bring back</span>';
                    popoutBtn.classList.replace('btn-outline-secondary', 'btn-secondary');
                }

            }

            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', initViewerControls);
            } else {
                initViewerControls();
            }
        })();
    </script>

{% endblock js %}
