// SuperLocalMemory V2 - Memories List + Sorting
// Depends on: core.js, modal.js (openMemoryDetail)
//
// Security: All dynamic values are escaped via escapeHtml() before DOM insertion.
// The innerHTML usage in renderMemoriesTable is safe because every interpolated
// value passes through escapeHtml(). Data comes from our own local SQLite DB only.
// nosemgrep: innerHTML-xss — all dynamic values escaped via escapeHtml()

// S9-DASH-07: active named filter ('high_reward' | 'being_forgotten' | null).
var _slmMemoryFilter = null;

function setMemoryFilter(name) {
    // Toggle: second click on same pill clears.
    _slmMemoryFilter = (_slmMemoryFilter === name) ? null : name;
    var pills = document.querySelectorAll('.mem-filter-pill');
    for (var i = 0; i < pills.length; i++) {
        var active = pills[i].getAttribute('data-filter') === _slmMemoryFilter;
        pills[i].classList.toggle('active', active);
    }
    loadMemories();
}

// v3.4.31 pagination state
var _slmPage = 0;
var _slmPageSize = 50;
var _slmLastTotal = 0;

async function loadMemories(page) {
    if (typeof page === 'number') _slmPage = Math.max(0, page);
    var category = document.getElementById('filter-category').value;
    var project = document.getElementById('filter-project').value;
    var limit = _slmPageSize;
    var offset = _slmPage * limit;
    var url = '/api/memories?limit=' + limit + '&offset=' + offset;
    if (category) url += '&category=' + encodeURIComponent(category);
    if (project) url += '&project_name=' + encodeURIComponent(project);
    if (_slmMemoryFilter) {
        url += '&filter=' + encodeURIComponent(_slmMemoryFilter);
    }

    showLoading('memories-list', 'Loading memories...');
    try {
        var response = await fetch(url);
        var data = await response.json();
        lastSearchResults = null;
        var exportBtn = document.getElementById('export-search-btn');
        if (exportBtn) exportBtn.style.display = 'none';
        _slmLastTotal = data.total || 0;
        renderMemoriesTable(data.memories, false);
        renderPaginationControls(data);
    } catch (error) {
        console.error('Error loading memories:', error);
        showEmpty('memories-list', 'exclamation-triangle', 'Failed to load memories');
    }
}

function renderPaginationControls(data) {
    var el = document.getElementById('memories-pagination');
    if (!el) return;
    var total = data.total || 0;
    var limit = data.limit || _slmPageSize;
    var offset = data.offset || 0;
    var showing = Math.min(offset + limit, total);
    var firstIdx = total === 0 ? 0 : offset + 1;
    var lastPage = Math.max(0, Math.ceil(total / limit) - 1);
    var prevDisabled = _slmPage <= 0 ? 'disabled' : '';
    var nextDisabled = _slmPage >= lastPage ? 'disabled' : '';
    el.innerHTML =
        '<div class="d-flex justify-content-between align-items-center mt-3 small">' +
          '<span class="text-muted">Showing ' + firstIdx + '\u2013' + showing + ' of ' + total + ' memories</span>' +
          '<div class="btn-group btn-group-sm">' +
            '<button type="button" class="btn btn-outline-secondary" ' + prevDisabled + ' onclick="loadMemories(' + (_slmPage - 1) + ')"><i class="bi bi-chevron-left"></i> Prev</button>' +
            '<button type="button" class="btn btn-outline-secondary disabled">Page ' + (_slmPage + 1) + ' / ' + (lastPage + 1) + '</button>' +
            '<button type="button" class="btn btn-outline-secondary" ' + nextDisabled + ' onclick="loadMemories(' + (_slmPage + 1) + ')">Next <i class="bi bi-chevron-right"></i></button>' +
          '</div>' +
        '</div>';
}

function renderMemoriesTable(memories, showScores) {
    var container = document.getElementById('memories-list');
    if (!memories || memories.length === 0) {
        showEmpty('memories-list', 'journal-x', 'No memories found. Try a different search or filter.');
        return;
    }

    window._slmMemories = memories;
    var scoreHeader = showScores ? '<th>Score</th>' : '';

    var rows = '';
    memories.forEach(function(mem, idx) {
        var content = mem.summary || mem.content || '';
        var contentPreview = content.length > 100 ? content.substring(0, 100) + '...' : content;
        var importance = mem.importance || 5;
        var importanceClass = importance >= 8 ? 'success' : importance >= 5 ? 'warning' : 'secondary';

        var scoreCell = '';
        if (showScores) {
            var score = mem.score || 0;
            var pct = Math.round(score * 100);
            var barColor = pct >= 70 ? '#43e97b' : pct >= 40 ? '#f9c74f' : '#f94144';
            scoreCell = '<td><span class="score-label">' + escapeHtml(String(pct)) + '%</span>'
                + '<div class="score-bar-container"><div class="score-bar">'
                + '<div class="score-bar-fill" style="width:' + pct + '%;background:' + barColor + '"></div>'
                + '</div></div></td>';
        }

        var memId = mem.memory_id || mem.id;
        var factId = mem.fact_id || '';
        var expandBtnHtml = '<button class="btn btn-sm btn-outline-secondary expand-facts-btn ms-1" data-memory-id="' + escapeHtml(String(memId)) + '" title="View atomic facts">&#9660;</button>';

        // S9-DASH-06: inline thumbs ↑/↓ on recall results. Writes a
        // reward label to action_outcomes via /api/behavioral/
        // report-outcome. Only shown when we have a fact_id (recall
        // path) since the outcome is keyed by memory_ids.
        var feedbackHtml = '';
        if (showScores && factId) {
            feedbackHtml = ''
                + '<span class="inline-feedback" data-fact-id="'
                + escapeHtml(String(factId)) + '" '
                + 'style="margin-left:8px; white-space:nowrap;">'
                + '<button type="button" class="btn btn-sm btn-outline-success fb-up" '
                + 'title="This was helpful (+1 reward)" '
                + 'style="padding:0 6px; font-size:11px;">👍</button> '
                + '<button type="button" class="btn btn-sm btn-outline-danger fb-down" '
                + 'title="Not helpful (0 reward)" '
                + 'style="padding:0 6px; font-size:11px;">👎</button>'
                + '</span>';
        }

        rows += '<tr data-mem-idx="' + idx + '">'
            + '<td>' + escapeHtml(String(mem.id)) + '</td>'
            + '<td><span class="badge bg-primary">' + escapeHtml(mem.category || 'None') + '</span></td>'
            + '<td><small>' + escapeHtml(mem.project_name || '-') + '</small></td>'
            + '<td class="memory-content" title="' + escapeHtml(content) + '">' + escapeHtml(contentPreview) + expandBtnHtml + feedbackHtml + '</td>'
            + scoreCell
            + '<td><span class="badge bg-' + importanceClass + ' badge-importance">' + escapeHtml(String(importance)) + '</span></td>'
            + '<td>' + escapeHtml(String(mem.cluster_id || '-')) + '</td>'
            + '<td><small>' + escapeHtml(formatDate(mem.created_at)) + '</small></td>'
            + '</tr>';
    });

    var tableHtml = '<table class="table table-hover memory-table"><thead><tr>'
        + '<th class="sortable" data-sort="id">ID</th>'
        + '<th class="sortable" data-sort="category">Category</th>'
        + '<th class="sortable" data-sort="project">Project</th>'
        + '<th>Content</th>'
        + scoreHeader
        + '<th class="sortable" data-sort="importance">Importance</th>'
        + '<th>Cluster</th>'
        + '<th class="sortable" data-sort="created">Created</th>'
        + '</tr></thead><tbody>' + rows + '</tbody></table>';

    // All values above escaped via escapeHtml() — safe for trusted local data
    container.textContent = '';
    container.insertAdjacentHTML('beforeend', tableHtml);

    var table = container.querySelector('table');
    if (table) {
        table.addEventListener('click', function(e) {
            var th = e.target.closest('th.sortable');
            if (th) { handleSort(th); return; }

            // Expand facts button
            var expandBtn = e.target.closest('.expand-facts-btn');
            if (expandBtn) {
                e.stopPropagation();
                var memId = expandBtn.getAttribute('data-memory-id');
                toggleFactsExpansion(expandBtn, memId);
                return;
            }

            // S9-DASH-06: inline thumbs ↑/↓.
            var fbUp = e.target.closest('.fb-up');
            var fbDown = e.target.closest('.fb-down');
            if (fbUp || fbDown) {
                e.stopPropagation();
                var btn = fbUp || fbDown;
                var wrapper = btn.closest('.inline-feedback');
                var fid = wrapper && wrapper.getAttribute('data-fact-id');
                if (!fid) return;
                var outcome = fbUp ? 'success' : 'failure';
                // Disable both buttons while the request is in flight.
                var allBtns = wrapper.querySelectorAll('button');
                for (var i = 0; i < allBtns.length; i++) {
                    allBtns[i].setAttribute('disabled', 'disabled');
                }
                btn.textContent = '…';
                fetch('/api/behavioral/report-outcome', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    credentials: 'same-origin',
                    body: JSON.stringify({
                        memory_ids: [fid],
                        outcome: outcome,
                        action_type: 'inline_feedback',
                        context: 'search/recall result',
                    }),
                }).then(function(r) { return r.json(); })
                .then(function(json) {
                    if (json && json.success) {
                        btn.textContent = fbUp ? '✓' : '✓';
                        btn.style.background = fbUp ? '#2d7a2d' : '#7a2d2d';
                        btn.style.borderColor = fbUp ? '#2d7a2d' : '#7a2d2d';
                        btn.style.color = '#fff';
                    } else {
                        btn.textContent = fbUp ? '👍' : '👎';
                        for (var j = 0; j < allBtns.length; j++) {
                            allBtns[j].removeAttribute('disabled');
                        }
                    }
                }).catch(function() {
                    btn.textContent = fbUp ? '👍' : '👎';
                    for (var k = 0; k < allBtns.length; k++) {
                        allBtns[k].removeAttribute('disabled');
                    }
                });
                return;
            }

            var row = e.target.closest('tr[data-mem-idx]');
            if (row && !e.target.closest('.expand-facts-btn')
                   && !e.target.closest('.inline-feedback')) {
                var idx = parseInt(row.getAttribute('data-mem-idx'), 10);
                if (window._slmMemories && window._slmMemories[idx]) {
                    openMemoryDetail(window._slmMemories[idx]);
                }
            }
        });
    }
}

// ============================================================================
// Column Sorting
// ============================================================================

var currentSort = { column: null, direction: 'asc' };

function handleSort(th) {
    var col = th.getAttribute('data-sort');
    if (!col) return;

    if (currentSort.column === col) {
        currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc';
    } else {
        currentSort.column = col;
        currentSort.direction = 'asc';
    }

    document.querySelectorAll('#memories-list th.sortable').forEach(function(h) {
        h.classList.remove('sort-asc', 'sort-desc');
    });
    th.classList.add('sort-' + currentSort.direction);

    if (!window._slmMemories) return;
    var memories = window._slmMemories.slice();
    var dir = currentSort.direction === 'asc' ? 1 : -1;

    memories.sort(function(a, b) {
        var av, bv;
        switch (col) {
            case 'id': return ((a.id || 0) - (b.id || 0)) * dir;
            case 'importance': return ((a.importance || 0) - (b.importance || 0)) * dir;
            case 'category':
                av = (a.category || '').toLowerCase(); bv = (b.category || '').toLowerCase();
                return av < bv ? -dir : av > bv ? dir : 0;
            case 'project':
                av = (a.project_name || '').toLowerCase(); bv = (b.project_name || '').toLowerCase();
                return av < bv ? -dir : av > bv ? dir : 0;
            case 'created':
                av = a.created_at || ''; bv = b.created_at || '';
                return av < bv ? -dir : av > bv ? dir : 0;
            case 'score': return ((a.score || 0) - (b.score || 0)) * dir;
            default: return 0;
        }
    });

    window._slmMemories = memories;
    var showScores = memories.length > 0 && typeof memories[0].score === 'number';
    renderMemoriesTable(memories, showScores);
}

// ============================================================================
// Navigation from Graph (v2.6.5)
// ============================================================================

// Scroll to a specific memory by ID (called from graph double-click)
function scrollToMemory(memoryId) {
    const container = document.getElementById('memories-list');
    if (!container) return;

    // Find the memory in current list
    if (!window._slmMemories) {
        console.warn('No memories loaded yet. Loading all memories...');
        loadMemories().then(() => {
            setTimeout(() => scrollToMemoryInTable(memoryId), 500);
        });
        return;
    }

    scrollToMemoryInTable(memoryId);
}

async function toggleFactsExpansion(btn, memoryId) {
    var row = btn.closest('tr');
    if (!row) return;
    var existingExpansion = row.nextElementSibling;
    if (existingExpansion && existingExpansion.classList.contains('facts-expansion-row')) {
        existingExpansion.remove();
        btn.innerHTML = '&#9660;';
        return;
    }

    btn.innerHTML = '&#8987;';
    try {
        var resp = await fetch('/api/memories/' + encodeURIComponent(memoryId) + '/facts');
        var data = await resp.json();
        var expRow = document.createElement('tr');
        expRow.className = 'facts-expansion-row';
        var expCell = document.createElement('td');
        expCell.colSpan = 8;
        expCell.style.cssText = 'background:#f8f9fa; padding:8px 16px;';

        if (data.facts && data.facts.length > 0) {
            var label = document.createElement('small');
            label.className = 'text-muted';
            label.textContent = data.fact_count + ' atomic facts:';
            expCell.appendChild(label);

            data.facts.forEach(function(f, i) {
                var fDiv = document.createElement('div');
                fDiv.className = 'small py-1' + (i < data.facts.length - 1 ? ' border-bottom' : '');
                var badge = document.createElement('span');
                badge.className = 'badge bg-secondary me-1';
                badge.style.fontSize = '0.65rem';
                badge.textContent = f.fact_type;
                fDiv.appendChild(badge);
                fDiv.appendChild(document.createTextNode(f.content.substring(0, 200)));
                expCell.appendChild(fDiv);
            });
        } else {
            expCell.textContent = 'No atomic facts found for this memory.';
        }

        expRow.appendChild(expCell);
        row.parentNode.insertBefore(expRow, row.nextSibling);
        btn.innerHTML = '&#9650;';
    } catch (err) {
        btn.innerHTML = '&#9660;';
        console.error('Failed to load facts:', err);
    }
}

function scrollToMemoryInTable(memoryId) {
    const memId = String(memoryId);

    // Find the memory index
    let idx = -1;
    if (window._slmMemories) {
        idx = window._slmMemories.findIndex(m => String(m.id) === memId);
    }

    if (idx === -1) {
        console.warn(`Memory #${memoryId} not found in current list`);
        return;
    }

    // Find the table row
    const row = document.querySelector(`tr[data-mem-idx="${idx}"]`);
    if (!row) {
        console.warn(`Row for memory #${memoryId} not found in DOM`);
        return;
    }

    // Scroll to row
    row.scrollIntoView({ behavior: 'smooth', block: 'center' });

    // Highlight temporarily
    row.style.backgroundColor = '#fff3cd';
    setTimeout(() => {
        row.style.backgroundColor = '';
    }, 2000);
}
