/**
 * Library Search UI Controller
 *
 * Manages search mode switching (hybrid/text/semantic), debounced input,
 * hybrid search orchestration, and DOM reordering for the library page.
 *
 * Depends on: window.LibrarySearch, window.SemanticSearch (loaded via defer before this file)
 * Depends on: window.DEFAULT_LIBRARY_COLLECTION_ID, window.COLLECTIONS_DATA (set inline in template)
 */
(function() {

// --- Search mode state ---
const SM = { HYBRID: 'hybrid', TEXT: 'text', SEMANTIC: 'semantic' };
let searchMode = SM.HYBRID;
let inputDebounceTimer = null;
let semanticDebounceTimer = null;
let hybridSearchId = 0;
const documentsContainer = document.getElementById('documents-container');
const semanticResultsContainer = document.getElementById('semantic-results-container');
const searchNotice = document.getElementById('library-search-notice');
// Save original card order so hybrid search reorder can be reversed
const originalCardOrder = documentsContainer
    ? Array.from(documentsContainer.querySelectorAll('.ldr-document-card'))
    : [];

// Initialize LibrarySearch when ready
document.addEventListener('DOMContentLoaded', function() {
    if (window.LibrarySearch && typeof DEFAULT_LIBRARY_COLLECTION_ID !== 'undefined') {
        window.LibrarySearch.initLibrarySearch(DEFAULT_LIBRARY_COLLECTION_ID, COLLECTIONS_DATA || []);
    }
});

// --- Search mode toggle ---
const searchModeMenu = document.getElementById('search-mode-menu');
if (searchModeMenu) {
    searchModeMenu.addEventListener('click', function(e) {
        const item = e.target.closest('.dropdown-item');
        if (!item) return;
        e.preventDefault();
        const mode = item.dataset.mode;
        if (!mode || mode === searchMode) return;
        searchMode = mode;
        searchModeMenu.querySelectorAll('.dropdown-item').forEach(function(i) { i.classList.remove('active'); });
        item.classList.add('active');
        const icons = { hybrid: 'fa-brain', text: 'fa-font', semantic: 'fa-brain' };
        const labelTexts = { hybrid: 'AI Hybrid', text: 'Text Only', semantic: 'AI Only' };
        const placeholders = { hybrid: 'AI Hybrid: titles & authors + AI content search...', text: 'Text: filter by title, authors, DOI...', semantic: 'AI: search inside document content...' };
        const btn = document.getElementById('search-mode-btn');
        if (btn && labelTexts[mode]) {
            window.safeUpdateButton(btn, icons[mode], ' ' + labelTexts[mode]);
        }
        const input = document.getElementById('search-documents');
        if (input) input.placeholder = placeholders[mode];
        // Clean up badges, snippets, and restore original card order
        clearHybridState();
        handleSearchInput();
    });
}

// --- Collection dropdown: conditional reload ---
const collectionFilter = document.getElementById('filter-collection');
if (collectionFilter) {
    collectionFilter.addEventListener('change', function() {
        if (searchMode === SM.TEXT) {
            // TEXT mode: server-side reload (existing behavior)
            const collection = this.value;
            const urlParams = new URLSearchParams(window.location.search);
            if (collection) {
                urlParams.set('collection', collection);
            } else {
                urlParams.delete('collection');
            }
            urlParams.delete('page');
            window.location.search = urlParams.toString();
        } else {
            // SEMANTIC/HYBRID mode: invalidate in-flight searches and re-trigger
            hybridSearchId++;
            handleSearchInput();
        }
    });
}

// --- Dropdown filters ---
const domainFilter = document.getElementById('filter-domain');
const researchFilter = document.getElementById('filter-research');
const dateFilter = document.getElementById('filter-date');
if (domainFilter) {
    domainFilter.addEventListener('change', function() {
        if (searchMode === SM.TEXT) {
            const urlParams = new URLSearchParams(window.location.search);
            if (this.value) {
                urlParams.set('domain', this.value);
            } else {
                urlParams.delete('domain');
            }
            urlParams.delete('page');
            window.location.search = urlParams.toString();
        } else {
            hybridSearchId++;
            handleSearchInput();
        }
    });
}
if (researchFilter) {
    researchFilter.addEventListener('change', function() {
        if (searchMode === SM.TEXT) {
            const urlParams = new URLSearchParams(window.location.search);
            if (this.value) {
                urlParams.set('research', this.value);
            } else {
                urlParams.delete('research');
            }
            urlParams.delete('page');
            window.location.search = urlParams.toString();
        } else {
            hybridSearchId++;
            handleSearchInput();
        }
    });
}
if (dateFilter) {
    dateFilter.addEventListener('change', function() {
        if (searchMode === SM.TEXT) {
            const urlParams = new URLSearchParams(window.location.search);
            if (this.value) {
                urlParams.set('date', this.value);
            } else {
                urlParams.delete('date');
            }
            urlParams.delete('page');
            window.location.search = urlParams.toString();
        } else {
            hybridSearchId++;
            handleSearchInput();
        }
    });
}

// --- Search input: mode-aware with debounce ---
const searchInput = document.getElementById('search-documents');
if (searchInput) {
    searchInput.addEventListener('input', function() {
        clearTimeout(inputDebounceTimer);
        inputDebounceTimer = setTimeout(handleSearchInput, 250);
    });
}

// Client-side filter (domain and research use server-side URL nav in TEXT mode,
// but still need client-side filtering for HYBRID/SEMANTIC modes)
function filterDocuments() {
    const domain = document.getElementById('filter-domain').value;
    const research = document.getElementById('filter-research').value;
    const search = document.getElementById('search-documents').value.toLowerCase();

    document.querySelectorAll('.ldr-document-card').forEach(function(card) {
        let show = true;

        if (domain && card.dataset.domain !== domain) {
            show = false;
        }
        if (research && card.dataset.research !== research) {
            show = false;
        }
        if (search && !card.textContent.toLowerCase().includes(search)) {
            show = false;
        }

        card.style.display = show ? '' : 'none';
    });
}

// --- Main search handler ---
function handleSearchInput() {
    const searchTerm = (document.getElementById('search-documents').value || '').trim();

    // Empty search: revert to showing all cards in original order
    if (!searchTerm) {
        clearTimeout(semanticDebounceTimer);
        clearHybridState();
        if (documentsContainer) documentsContainer.style.display = 'grid';
        if (semanticResultsContainer) { semanticResultsContainer.style.display = 'none'; semanticResultsContainer.innerHTML = ''; }
        if (searchNotice) searchNotice.style.display = 'none';
        filterDocuments();
        return;
    }

    if (searchMode === SM.TEXT) {
        if (documentsContainer) documentsContainer.style.display = 'grid';
        if (semanticResultsContainer) semanticResultsContainer.style.display = 'none';
        if (searchNotice) searchNotice.style.display = 'none';
        filterDocuments();
    } else if (searchMode === SM.SEMANTIC) {
        if (documentsContainer) documentsContainer.style.display = 'none';
        if (semanticResultsContainer) semanticResultsContainer.style.display = 'block';
        clearTimeout(semanticDebounceTimer);
        semanticDebounceTimer = setTimeout(function() { runSemanticSearch(searchTerm); }, 500);
    } else {
        // Hybrid mode
        if (documentsContainer) documentsContainer.style.display = 'grid';
        if (semanticResultsContainer) semanticResultsContainer.style.display = 'none';
        filterDocuments();
        clearTimeout(semanticDebounceTimer);
        const currentId = ++hybridSearchId;
        semanticDebounceTimer = setTimeout(function() { runHybridSearch(searchTerm, currentId); }, 500);
    }
}

// --- Semantic search execution ---
async function runSemanticSearch(query) {
    if (!window.LibrarySearch) return;
    if (semanticResultsContainer) {
        // bearer:disable javascript_lang_dangerous_insert_html
        semanticResultsContainer.innerHTML = '<div class="ldr-hybrid-loading"><div class="ldr-spinner" style="width:16px;height:16px;border-width:2px;"></div> Searching content...</div>';
    }
    try {
        const collectionId = getActiveSearchCollectionId();
        let results;
        if (collectionId) {
            const resp = await window.LibrarySearch.performSemanticSearch(collectionId, query, 20);
            results = (resp && resp.success) ? resp.results : [];
        } else {
            const ids = window.LibrarySearch.getIndexedCollectionIds();
            if (ids.length === 0) {
                // bearer:disable javascript_lang_dangerous_insert_html
                showSearchNotice('No collections have been indexed yet. <a href="/library/collections">Index a collection</a> to enable semantic search.');
                if (semanticResultsContainer) semanticResultsContainer.innerHTML = '';
                return;
            }
            // bearer:disable javascript_lang_dangerous_insert_html
            showSearchNotice('Searching across ' + ids.length + ' indexed collection' + (ids.length > 1 ? 's' : '') + '.');
            results = await window.LibrarySearch.searchAllCollections(ids, query, 20);
        }
        if (searchMode !== SM.SEMANTIC) return; // mode changed
        results = postFilterSemanticResults(results);
        window.LibrarySearch.renderSemanticResults(results, semanticResultsContainer, query);
    } catch (err) {
        if (typeof SafeLogger !== 'undefined') SafeLogger.error('Semantic search error:', err);
        if (semanticResultsContainer) {
            // bearer:disable javascript_lang_dangerous_insert_html
            semanticResultsContainer.innerHTML = '<div class="ldr-empty-state"><i class="fas fa-exclamation-triangle fa-2x"></i><p>Search failed. Please try again.</p></div>';
        }
    }
}

// --- Hybrid search execution ---
async function runHybridSearch(query, searchId) {
    if (!window.LibrarySearch || !window.SemanticSearch) return;

    const loadingDiv = document.createElement('div');
    loadingDiv.className = 'ldr-hybrid-loading';
    loadingDiv.id = 'hybrid-loading-indicator';
    // bearer:disable javascript_lang_dangerous_insert_html
    loadingDiv.innerHTML = '<div class="ldr-spinner" style="width:16px;height:16px;border-width:2px;"></div> Searching content...';
    if (documentsContainer) documentsContainer.appendChild(loadingDiv);

    try {
        const collectionId = getActiveSearchCollectionId();
        let semanticResults;
        if (collectionId) {
            const resp = await window.LibrarySearch.performSemanticSearch(collectionId, query, 20);
            semanticResults = (resp && resp.success) ? resp.results : [];
        } else {
            const ids = window.LibrarySearch.getIndexedCollectionIds();
            if (ids.length === 0) {
                removeHybridLoading();
                // bearer:disable javascript_lang_dangerous_insert_html
                showSearchNotice('No indexed collections. <a href="/library/collections">Index a collection</a> for AI search.');
                return;
            }
            semanticResults = await window.LibrarySearch.searchAllCollections(ids, query, 20);
        }

        if (searchId !== hybridSearchId || searchMode !== SM.HYBRID) {
            removeHybridLoading();
            return;
        }

        removeHybridLoading();
        semanticResults = postFilterSemanticResults(semanticResults);

        const visibleCards = Array.from(document.querySelectorAll('.ldr-document-card')).filter(function(c) { return c.style.display !== 'none'; });
        const textResults = visibleCards.map(function(c) { return { id: c.dataset.docId, card: c }; });

        const tiered = window.SemanticSearch.buildTieredResults(
            textResults, semanticResults,
            { textIdKey: 'id', semanticIdKey: 'document_id' }
        );

        renderMergedLibraryResults(tiered, query);

    } catch (err) {
        removeHybridLoading();
        if (typeof SafeLogger !== 'undefined') SafeLogger.error('Hybrid search error:', err);
    }
}

// --- Render merged library results (DOM reorder) ---
function renderMergedLibraryResults(tiered, query) {
    if (!documentsContainer) return;
    const fragment = document.createDocumentFragment();
    const esc = window.escapeHtml || function(s) { return String(s || '').replace(/[&<>"']/g, function(m) { return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":"&#39;"}[m]; }); };

    const renderSnippet = window.SemanticSearch && window.SemanticSearch.renderSnippet;

    for (let i = 0; i < tiered.tier1.length; i++) {
        const entry = tiered.tier1[i];
        const card = entry.historyItem.card;
        if (card) {
            const header = card.querySelector('.card-header');
            if (header && !header.querySelector('[data-similarity]')) {
                const badge = document.createElement('span');
                badge.className = 'ldr-ai-match-badge';
                badge.dataset.similarity = entry.semanticMatch.similarity;
                // bearer:disable javascript_lang_dangerous_insert_html
                badge.innerHTML = '<i class="fas fa-brain" aria-hidden="true"></i> ' + esc(String(entry.semanticMatch.similarity)) + '% match';
                header.appendChild(badge);
            }
            // Inject semantic snippet into card body
            if (entry.semanticMatch.snippet && renderSnippet) {
                const existing = card.querySelector('.ldr-library-snippet');
                if (existing) existing.remove();
                const snippetDiv = document.createElement('div');
                snippetDiv.className = 'ldr-library-snippet';
                // bearer:disable javascript_lang_dangerous_insert_html
                // eslint-disable-next-line no-unsanitized/property -- audited 2026-03-28: all interpolations use escapeHtml/esc, numeric coercion, or hardcoded strings
                snippetDiv.innerHTML = '<small class="text-muted"><i class="fas fa-brain" aria-hidden="true"></i> Matched content:</small>' +
                    '<div>' + renderSnippet(entry.semanticMatch.snippet, query) + '</div>';
                const body = card.querySelector('.card-body');
                if (body) body.appendChild(snippetDiv);
            }
            fragment.appendChild(card);
        }
    }

    for (let j = 0; j < tiered.tier2.length; j++) {
        const card2 = tiered.tier2[j].historyItem.card;
        if (card2) fragment.appendChild(card2);
    }

    if (tiered.tier3.length > 0 && window.SemanticSearch) {
        const divider = document.createElement('div');
        divider.className = 'ldr-hybrid-divider';
        divider.textContent = 'Also found in content';
        fragment.appendChild(divider);

        const config = window.LibrarySearch.getLibraryCardConfig();
        for (let k = 0; k < tiered.tier3.length; k++) {
            fragment.appendChild(window.SemanticSearch.createSemanticResultCard(tiered.tier3[k].semanticResult, config, query));
        }
    }

    documentsContainer.innerHTML = '';
    documentsContainer.appendChild(fragment);
}

// --- Helpers ---
function clearHybridState() {
    hybridSearchId++;
    document.querySelectorAll('.card-header [data-similarity]').forEach(function(b) { b.remove(); });
    document.querySelectorAll('.ldr-library-snippet').forEach(function(el) { el.remove(); });
    for (let ci = 0; ci < originalCardOrder.length; ci++) {
        documentsContainer.appendChild(originalCardOrder[ci]);
    }
    documentsContainer.querySelectorAll('.ldr-semantic-result').forEach(function(el) { el.remove(); });
    documentsContainer.querySelectorAll('.ldr-hybrid-divider').forEach(function(el) { el.remove(); });
}

function getActiveSearchCollectionId() {
    const sel = document.getElementById('filter-collection');
    return (sel && sel.value) ? sel.value : null;
}

function postFilterSemanticResults(results) {
    const domain = document.getElementById('filter-domain').value;
    const research = document.getElementById('filter-research').value;
    const dateEl = document.getElementById('filter-date');
    const date = dateEl ? dateEl.value : '';
    if (!domain && !research && !date) return results;
    const now = new Date();
    return results.filter(function(r) {
        if (domain && r.domain && r.domain !== domain) return false;
        if (research && r.research_id && r.research_id !== research) return false;
        if (date && r.created_at) {
            const d = new Date(r.created_at);
            if (isNaN(d.getTime())) return false;
            if (date === 'today' && d.toDateString() !== now.toDateString()) return false;
            if (date === 'week' && now - d > 7 * 86400000) return false;
            if (date === 'month' && now - d > 30 * 86400000) return false;
        }
        return true;
    });
}

function showSearchNotice(html) {
    if (searchNotice) {
        // bearer:disable javascript_lang_dangerous_insert_html
        // eslint-disable-next-line no-unsanitized/property -- audited 2026-03-28: generic helper — callers verified to pass sanitized HTML only
        searchNotice.innerHTML = html;
        searchNotice.style.display = 'block';
    }
}

function removeHybridLoading() {
    const el = document.getElementById('hybrid-loading-indicator');
    if (el) el.remove();
}

})();
