{# Implements: REQ-p00006-A, REQ-d00010-A #}
{# Unified trace template — mode="view" for static HTML, mode="edit" for Flask server #}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    {% if mode == 'edit' %}
    <title>Trace Edit - Requirements Editor</title>
    {% else %}
    <title>Requirements Traceability</title>
    {% endif %}
    <style>
/* Implements: REQ-p00006-A */
{% include "partials/css/_base.css.j2" %}

/* 3-panel layout: fixed viewport */
body {
    overflow: hidden;
    height: 100vh;
    display: flex;
    flex-direction: column;
}

{% include "partials/css/_header.css.j2" %}
{% include "partials/css/_toolbar.css.j2" %}
{% include "partials/css/_buttons.css.j2" %}
{% include "partials/css/_toast.css.j2" %}
{% include "partials/css/_nav-panel.css.j2" %}
{% include "partials/css/_dividers.css.j2" %}
{% include "partials/css/_card-stack.css.j2" %}
{% include "partials/css/_edit-mode.css.j2" %}
{% include "partials/css/_file-viewer.css.j2" %}
/* Pygments syntax highlighting theme */
{% if pygments_css %}
{{ pygments_css }}
{% endif %}
{% if pygments_css_dark %}
{{ pygments_css_dark }}
{% endif %}
{% include "partials/css/_status-badges.css.j2" %}
{% include "partials/css/_coverage.css.j2" %}
{% include "partials/css/_topic-tags.css.j2" %}
{% include "partials/css/_legend.css.j2" %}
{% include "partials/css/_journey.css.j2" %}
{% include "partials/css/_dark-theme.css.j2" %}
/* Responsive */
@media (max-width: 768px) {
    .header { flex-direction: column; align-items: flex-start; }
    .header-center { min-width: 100%; }
    .layout { flex-direction: column; }
    .nav-panel { width: 100% !important; max-width: 100% !important; height: 40vh; border-right: none; border-bottom: 1px solid #e9ecef; }
    .file-viewer-panel { width: 100% !important; max-width: 100% !important; border-left: none; border-top: 1px solid #e9ecef; }
}
    </style>
</head>
<body{% if mode == 'edit' %} data-base-path="{{ base_path }}"{% endif %}>

{% include "partials/_header.html.j2" %}

{% include "partials/_toast_container.html.j2" %}

{% include "partials/_toolbar.html.j2" %}

<!-- =====================================================================
     3-PANEL LAYOUT (both modes)
     ===================================================================== -->

<div class="layout" id="layout">

    <!-- Nav Panel (Left) -->
    <nav class="nav-panel" id="nav-panel">
        <div class="nav-tabs">
            <button class="nav-tab active" data-kind="req" onclick="switchNavTab('req')">Req</button>
            <button class="nav-tab" data-kind="journey" onclick="switchNavTab('journey')">Journeys</button>
            <span class="nav-tab-spacer"></span>
            <button class="nav-tree-action" onclick="expandAllTreeNodes()" title="Expand all">&#9660;</button>
            <button class="nav-tree-action" onclick="collapseAllTreeNodes()" title="Collapse all">&#9654;</button>
        </div>
        <div class="nav-tree-container" id="nav-tree-container">
            <div style="padding:20px;color:#adb5bd;text-align:center;font-size:0.85rem;">Loading tree...</div>
        </div>
    </nav>

    <!-- Divider 1 (nav | cards) -->
    <div class="divider" id="divider-left"></div>

    <!-- Card Stack (Center) -->
    <div class="card-stack-panel" id="card-stack-panel">
        <div class="card-stack-header">
            <span id="card-stack-count">No cards open</span>
            <button class="btn" onclick="closeAllCards()" style="padding:3px 8px;font-size:0.75rem;">Close All</button>
        </div>
        <div class="card-stack-body" id="card-stack-body">
            <div class="card-stack-empty" id="card-stack-empty">
                <div class="card-stack-empty-icon">&#128196;</div>
                <div>Click a requirement in the tree to open it</div>
                <div style="font-size:0.75rem;">Cards will appear here</div>
            </div>
        </div>
    </div>

    <!-- Divider 2 (cards | file viewer) -->
    <div class="divider" id="divider-right" style="display:none;"></div>

    <!-- File Viewer Panel (Right) -->
    {% include "partials/_file_viewer.html.j2" %}

</div>

<!-- Journey data container (journey card rendering reads from API) -->
<div id="journey-data-container" style="display:none;">
    {% include "partials/_journey_tab.html.j2" %}
</div>

{% include "partials/_legend_modal.html.j2" %}

{% if mode == 'view' %}
<!-- =====================================================================
     EMBEDDED DATA
     ===================================================================== -->

<script type="application/json" id="tree-data">
{{ tree_data | tojson }}
</script>

<script type="application/json" id="source-files">
{{ source_files | tojson }}
</script>

<script type="application/json" id="node-index">
{{ node_index | tojson }}
</script>

<script type="application/json" id="coverage-index">
{{ coverage_index | tojson }}
</script>

<script type="application/json" id="status-data">
{{ status_data | tojson }}
</script>
{% endif %}

<!-- =====================================================================
     JAVASCRIPT
     ===================================================================== -->

<script>
const MODE = '{{ mode }}';

{% include "partials/js/_utils.js.j2" %}

{% include "partials/js/_api-adapter.js.j2" %}

// State (unified for both modes)
const editState = {
    enabled: false,
    openCards: new Map(),
    openCardOrder: [],
    dirtyFields: new Map(),
    mutationCount: 0,
    activeNavTab: 'req',
    treeData: [],
    collapsedTreeNodes: new Set(),
    searchDebounce: null,
    activeFilters: {
        levelPrd: false,
        levelOps: false,
        levelDev: false,
        uncommitted: false,
        changed: false,
        main: false,
        leaf: false,
        deprecated: false,
        roadmap: false,
        hiddenRepos: []
    },
    knownRepos: [],
    filterStatus: '',
    filterCoverage: '',
    fontSize: 14,
    theme: 'system',
    toolbarHidden: false
};
// Apply theme early to prevent flash of wrong theme
(function() {
    try {
        var m = document.cookie.match(new RegExp('(^| )elspais_trace_state=([^;]+)'));
        if (m) {
            var s = JSON.parse(decodeURIComponent(m[2]));
            if (s.theme) editState.theme = s.theme;
            if (s.fontSize) {
                editState.fontSize = s.fontSize;
                document.documentElement.style.fontSize = s.fontSize + 'px';
            }
        }
    } catch(e) {}
    // Apply theme immediately
    var html = document.documentElement;
    html.classList.remove('dark-theme', 'light-theme');
    if (editState.theme === 'dark') {
        html.classList.add('dark-theme');
    } else if (editState.theme === 'light') {
        html.classList.add('light-theme');
    } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
        html.classList.add('dark-theme');
    }
})();

{% include "partials/js/_cookie-persistence.js.j2" %}

{% include "partials/js/_search.js.j2" %}

{% if mode == 'edit' %}
{% include "partials/js/_edit-engine.js.j2" %}
{% endif %}

{% include "partials/js/_nav-tree.js.j2" %}
{% include "partials/js/_card-stack.js.j2" %}

// Legend toggle (both modes)
function toggleLegend() {
    var modal = document.getElementById('legend-modal');
    modal.classList.toggle('visible');
}
function closeLegendOnOverlay(event) {
    if (event.target === event.currentTarget) {
        toggleLegend();
    }
}

// Journey ref click: open card (both modes)
function switchToReqTab(reqId) {
    openCard(reqId);
}

// Hamburger menu (both modes)
function toggleHamburgerMenu() {
    document.getElementById('hamburger-dropdown').classList.toggle('visible');
}
function closeHamburgerMenu() {
    document.getElementById('hamburger-dropdown').classList.remove('visible');
}
document.addEventListener('click', function(e) {
    var menu = document.getElementById('hamburger-menu');
    if (menu && !menu.contains(e.target)) {
        closeHamburgerMenu();
    }
});

// Font size (both modes)
function adjustFontSize(delta) {
    var current = editState.fontSize || 14;
    var newSize = Math.max(10, Math.min(20, current + delta));
    editState.fontSize = newSize;
    document.documentElement.style.fontSize = newSize + 'px';
    var display = document.getElementById('font-size-display');
    if (display) display.textContent = newSize + 'px';
    saveState();
}

// Theme (both modes)
function setTheme(theme) {
    editState.theme = theme;
    applyTheme();
    document.querySelectorAll('.theme-btn').forEach(function(b) {
        b.classList.toggle('active', b.dataset.theme === theme);
    });
    saveState();
}

function applyTheme() {
    var theme = editState.theme || 'system';
    var html = document.documentElement;
    html.classList.remove('dark-theme', 'light-theme');
    if (theme === 'dark') {
        html.classList.add('dark-theme');
    } else if (theme === 'light') {
        // light = no dark-theme class, even if system prefers dark
        html.classList.add('light-theme');
    } else {
        // system: check OS preference
        if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
            html.classList.add('dark-theme');
        }
    }
}

// Listen for OS theme changes (for system mode)
if (window.matchMedia) {
    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
        if (editState.theme === 'system') applyTheme();
    });
}

// Toolbar toggle (both modes)
function toggleToolbar() {
    editState.toolbarHidden = !editState.toolbarHidden;
    var toolbar = document.getElementById('edit-toolbar');
    var btn = document.getElementById('filter-toggle-btn');
    if (toolbar) toolbar.classList.toggle('toolbar-hidden', editState.toolbarHidden);
    if (btn) btn.classList.toggle('dimmed', editState.toolbarHidden);
    saveState();
}

{% include "partials/js/_file-viewer.js.j2" %}
{% include "partials/js/_divider.js.j2" %}

// Keyboard Shortcuts (both modes)
document.addEventListener('keydown', function(e) {
    if (e.key === 'Escape') {
        var legendModal = document.getElementById('legend-modal');
        if (legendModal && legendModal.classList.contains('visible')) {
            toggleLegend();
        } else if (document.getElementById('file-viewer-panel').classList.contains('open')) {
            closeFileViewer();
        }
    }
    if (e.key === 'k' && (e.ctrlKey || e.metaKey)) {
        e.preventDefault();
        document.getElementById('search-input').focus();
    }
    {% if mode == 'edit' %}
    if (e.key === 'e' && (e.ctrlKey || e.metaKey)) {
        e.preventDefault();
        toggleEditMode();
    }
    if (e.key === 'z' && (e.ctrlKey || e.metaKey) && !e.target.isContentEditable && e.target.tagName !== 'INPUT') {
        e.preventDefault();
        doUndo();
    }
    {% endif %}
});

// Initialize
document.addEventListener('DOMContentLoaded', function() {
    loadTreeData();  // loads tree data, updates header stats, renders nav tree
    initDividers();
    initSearch();
    {% if mode == 'edit' %}
    refreshDirtyCount();
    {% endif %}

    var saved = loadState();
    if (saved) {
        if (saved.activeNavTab) {
            // Migrate removed tabs to 'req'
            var navTab = (saved.activeNavTab === 'code' || saved.activeNavTab === 'test') ? 'req' : saved.activeNavTab;
            editState.activeNavTab = navTab;
            document.querySelectorAll('.nav-tab').forEach(function(tab) {
                tab.classList.toggle('active', tab.dataset.kind === navTab);
            });
        }
        {% if mode == 'edit' %}
        if (saved.editEnabled) {
            toggleEditMode();
        }
        {% endif %}
        if (saved.collapsedTreeNodes && Array.isArray(saved.collapsedTreeNodes)) {
            editState.collapsedTreeNodes = new Set(saved.collapsedTreeNodes);
        }
        // Restore nav tree filters
        if (saved.activeFilters) {
            Object.assign(editState.activeFilters, saved.activeFilters);
            // Update header stat badge dimmed state (null-guard for elements)
            var statPrd = document.getElementById('stat-prd');
            var statOps = document.getElementById('stat-ops');
            var statDev = document.getElementById('stat-dev');
            var statMain = document.getElementById('stat-main');
            if (statPrd) statPrd.classList.toggle('dimmed', !!editState.activeFilters.levelPrd);
            if (statOps) statOps.classList.toggle('dimmed', !!editState.activeFilters.levelOps);
            if (statDev) statDev.classList.toggle('dimmed', !!editState.activeFilters.levelDev);
            if (statMain) statMain.classList.toggle('dimmed', !!editState.activeFilters.main);
            // Ensure hiddenRepos is an array
            if (!Array.isArray(editState.activeFilters.hiddenRepos)) {
                editState.activeFilters.hiddenRepos = [];
            }
            // Update toolbar git filter buttons (null-guard)
            var btnUncommitted = document.getElementById('edit-btn-uncommitted');
            var btnChanged = document.getElementById('edit-btn-changed');
            if (btnUncommitted) btnUncommitted.classList.toggle('active', !!editState.activeFilters.uncommitted);
            if (btnChanged) btnChanged.classList.toggle('active', !!editState.activeFilters.changed);
            // Update checkboxes (null-guard)
            var leafCb = document.getElementById('edit-toggle-leaf');
            if (leafCb) leafCb.checked = !!editState.activeFilters.leaf;
            var deprecatedCb = document.getElementById('edit-toggle-deprecated');
            if (deprecatedCb) deprecatedCb.checked = !!editState.activeFilters.deprecated;
            var roadmapCb = document.getElementById('edit-toggle-roadmap');
            if (roadmapCb) roadmapCb.checked = !!editState.activeFilters.roadmap;
        }
        if (saved.filterStatus) {
            editState.filterStatus = saved.filterStatus;
            var filterStatusSel = document.getElementById('edit-filter-status');
            if (filterStatusSel) filterStatusSel.value = saved.filterStatus;
        }
        if (saved.filterCoverage) {
            editState.filterCoverage = saved.filterCoverage;
            var filterCovSel = document.getElementById('edit-filter-coverage');
            if (filterCovSel) filterCovSel.value = saved.filterCoverage;
        }
        // Restore font size
        if (saved.fontSize) {
            editState.fontSize = saved.fontSize;
            document.documentElement.style.fontSize = saved.fontSize + 'px';
            var fsDisplay = document.getElementById('font-size-display');
            if (fsDisplay) fsDisplay.textContent = saved.fontSize + 'px';
        }
        // Restore theme
        if (saved.theme) {
            editState.theme = saved.theme;
            applyTheme();
            document.querySelectorAll('.theme-btn').forEach(function(b) {
                b.classList.toggle('active', b.dataset.theme === saved.theme);
            });
        }
        // Restore toolbar visibility
        if (saved.toolbarHidden) {
            editState.toolbarHidden = true;
            var tb = document.getElementById('edit-toolbar');
            var ftb = document.getElementById('filter-toggle-btn');
            if (tb) tb.classList.add('toolbar-hidden');
            if (ftb) ftb.classList.add('dimmed');
        }
        // Restore panel widths
        if (saved.navPanelWidth) {
            document.getElementById('nav-panel').style.width = saved.navPanelWidth;
        }
        if (saved.fileViewerWidth) {
            document.getElementById('file-viewer-panel').style.width = saved.fileViewerWidth;
        }
        if (saved.openCardIds && saved.openCardIds.length > 0) {
            var collapsedSet = new Set(saved.collapsedCards || []);
            var ids = saved.openCardIds.slice().reverse();
            (async function restoreCards() {
                for (var i = 0; i < ids.length; i++) {
                    var id = ids[i];
                    var data = await apiFetch('/api/node/' + encodeURIComponent(id));
                    if (data) {
                        editState.openCards.set(id, {
                            data: data,
                            collapsed: collapsedSet.has(id),
                            kind: data.kind
                        });
                        editState.openCardOrder.push(id);
                    }
                }
                editState.openCardOrder.reverse();
                renderCardStack();
                updateNavSelection();
                // Prefetch coverage for restored requirement cards
                editState.openCards.forEach(function(info, id) {
                    if (info.data && info.data.kind === 'requirement') {
                        prefetchCoverage(id);
                    }
                });
                {% if mode == 'edit' %}
                if (editState.enabled) {
                    document.querySelectorAll('.card-assertion-text').forEach(function(el) {
                        el.contentEditable = 'true';
                    });
                    document.querySelectorAll('.edit-only').forEach(function(el) {
                        el.style.display = '';
                    });
                }
                {% endif %}
            })();
        }
    }
});
</script>

</body>
</html>
