/**
 * History Semantic Search Component
 *
 * Provides semantic search functionality over research history:
 * - Load indexing status
 * - Trigger indexing with progress
 * - Perform semantic search (called from history.js toggle)
 * - Display results with snippets and scores
 */
(function() {

// URL validation: isSafeUrl provided by SemanticSearch (semantic_search.js)
// Use shared escapeHtml from xss-protection.js (loaded via base.html),
// with a safe fallback if not available.
const escapeHtml = window.escapeHtml || function(text) {
    if (text === null || text === undefined) return '';
    const div = document.createElement('div');
    div.textContent = String(text);
    return div.innerHTML;
};

// State
let isIndexing = false;
let semanticPanelExpanded = true;
let cachedCollectionId = null;
let indexingPollInterval = null;
let pollErrorCount = 0;

/**
 * Initialize the semantic search component
 */
async function initSemanticSearch() {
    // Load initial indexing status (also caches collection ID)
    await loadIndexingStatus();
    // Resume polling if indexing was already in progress
    await checkAndResumeIndexing();
}

/**
 * Toggle the semantic search panel visibility
 */
function toggleSemanticPanel() {
    const content = document.getElementById('semantic-panel-content');
    const toggle = document.getElementById('semantic-panel-toggle');
    const header = document.getElementById('semantic-panel-header');

    if (content && toggle) {
        semanticPanelExpanded = !semanticPanelExpanded;
        content.style.display = semanticPanelExpanded ? 'block' : 'none';
        toggle.className = semanticPanelExpanded
            ? 'fas fa-chevron-down'
            : 'fas fa-chevron-right';
        if (header) {
            header.setAttribute('aria-expanded', semanticPanelExpanded ? 'true' : 'false');
        }
    }
}

/**
 * Load indexing status from the API
 */
async function loadIndexingStatus() {
    try {
        const response = await fetch(URLS.LIBRARY_API.RESEARCH_HISTORY_COLLECTION);
        if (!response.ok) {
            throw new Error(`Server returned ${response.status}`);
        }
        const data = await response.json();

        if (data.success) {
            cachedCollectionId = data.collection_id || null;

            const indexedCountEl = document.getElementById('indexed-count');
            const totalCountEl = document.getElementById('total-count');
            if (indexedCountEl) indexedCountEl.textContent = data.indexed_documents || 0;
            if (totalCountEl) totalCountEl.textContent = data.total_documents || 0;

            // Update button state
            const indexBtn = document.getElementById('index-all-btn');
            if (indexBtn) {
                const allIndexed = data.indexed_documents >= data.total_documents;
                indexBtn.disabled = allIndexed && data.total_documents > 0;
                if (allIndexed && data.total_documents > 0) {
                    indexBtn.innerHTML = '<i class="fas fa-check"></i> All Indexed';
                }
            }
        }
    } catch (error) {
        SafeLogger.error('Failed to load indexing status:', error);
    }
}

/**
 * Trigger indexing of all research history
 */
async function triggerIndexing() {
    if (isIndexing) return;
    isIndexing = true;  // Set immediately to prevent double-click race

    const indexBtn = document.getElementById('index-all-btn');
    const progressDiv = document.getElementById('indexing-progress');
    const progressBar = document.getElementById('indexing-progress-bar');
    const progressText = document.getElementById('indexing-progress-text');

    if (!cachedCollectionId) {
        await loadIndexingStatus();
    }
    if (!cachedCollectionId) {
        if (progressText) {
            progressText.textContent = 'Collection not available. Please refresh the page.';
            progressText.style.color = 'var(--error-color)';
        }
        // Reset the in-progress flag we set synchronously at the top of this
        // function. The early `if (isIndexing) return` guard makes concurrent
        // overlap impossible.
        // eslint-disable-next-line require-atomic-updates
        isIndexing = false;
        return;
    }

    // Show progress UI
    if (indexBtn) {
        indexBtn.disabled = true;
        indexBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Indexing...';
    }
    if (progressDiv) progressDiv.style.display = 'block';
    if (progressBar) progressBar.style.width = '0%';
    if (progressText) {
        progressText.textContent = 'Starting...';
        progressText.style.color = '';  // reset from any prior error styling
    }

    const csrfToken = (window.api && window.api.getCsrfToken)
        ? window.api.getCsrfToken()
        : (document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '');

    // Step 1: Convert any unconverted research entries to documents (fast, synchronous)
    try {
        if (progressText) progressText.textContent = 'Converting research to documents...';

        const convertResp = await fetch(URLS.LIBRARY_API.RESEARCH_HISTORY_CONVERT_ALL, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken,
            },
            body: JSON.stringify({}),
        });

        if (!convertResp.ok) {
            SafeLogger.warn('Convert-all returned ' + convertResp.status);
        } else {
            const convertData = await convertResp.json();
            if (convertData.converted > 0) {
                SafeLogger.log('Converted ' + convertData.converted + ' research entries to documents');
            }
        }
    } catch (convertError) {
        // Non-fatal: conversion may have already happened via auto-hook
        SafeLogger.warn('Convert-all request failed, proceeding to indexing:', convertError);
    }

    // Step 2: Start background indexing via POST
    if (progressText) progressText.textContent = 'Starting indexing...';

    try {
        const startResp = await fetch(URLBuilder.build(URLS.LIBRARY_API.COLLECTION_INDEX_START, cachedCollectionId), {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken,
            },
            body: JSON.stringify({ force_reindex: false }),
        });

        if (!startResp.ok && startResp.status !== 409) {
            throw new Error(`Server returned ${startResp.status}`);
        }

        let startData;
        try {
            startData = await startResp.json();
        } catch {
            throw new Error(`Server returned ${startResp.status}: unable to parse response`);
        }

        if (!startData.success && startResp.status !== 409) {
            throw new Error(startData.error || 'Failed to start indexing');
        }

        // 409 means already running — just start polling
        SafeLogger.log('Indexing started, beginning polling');
    } catch (startError) {
        SafeLogger.error('Error starting indexing:', startError);
        // Reset the in-progress flag we set synchronously at the top; the
        // early-return guard above prevents concurrent overlap.
        // eslint-disable-next-line require-atomic-updates
        isIndexing = false;
        if (progressText) {
            progressText.textContent = `Error: ${startError.message}`;
            progressText.style.color = 'var(--error-color)';
        }
        if (indexBtn) {
            indexBtn.disabled = false;
            indexBtn.innerHTML = '<i class="fas fa-sync"></i> Index All';
        }
        return;
    }

    // Step 3: Poll for status every 2 seconds
    startPolling();
}

/**
 * Start polling the index status endpoint every 2 seconds
 */
function startPolling() {
    // Reset error counter for this new polling session
    pollErrorCount = 0;

    // Clear any existing interval
    if (indexingPollInterval) {
        clearInterval(indexingPollInterval);
    }

    const indexBtn = document.getElementById('index-all-btn');
    const progressDiv = document.getElementById('indexing-progress');
    const progressBar = document.getElementById('indexing-progress-bar');
    const progressText = document.getElementById('indexing-progress-text');

    indexingPollInterval = setInterval(async () => {
        try {
            const response = await fetch(URLBuilder.build(URLS.LIBRARY_API.COLLECTION_INDEX_STATUS, cachedCollectionId));
            if (!response.ok) {
                throw new Error(`Status endpoint returned ${response.status}`);
            }
            const data = await response.json();

            // Reset error counter on every successful response
            pollErrorCount = 0;

            // Update progress bar
            if (data.progress_total > 0) {
                const percent = Math.round((data.progress_current / data.progress_total) * 100);
                if (progressBar) progressBar.style.width = percent + '%';
            }
            if (data.progress_message && progressText) {
                progressText.textContent = data.progress_message;
            }

            // Stop polling on terminal states
            if (ResearchStates.isTerminal(data.status) || data.status === 'idle') {
                clearInterval(indexingPollInterval);
                indexingPollInterval = null;
                isIndexing = false;

                if (ResearchStates.isCompleted(data.status)) {
                    if (progressBar) progressBar.style.width = '100%';
                    if (progressText) progressText.textContent = data.progress_message || 'Indexing complete!';
                } else if (ResearchStates.isFailed(data.status)) {
                    if (progressText) {
                        progressText.textContent = `Indexing failed: ${data.error_message || 'Unknown error'}`;
                        progressText.style.color = 'var(--error-color)';
                    }
                } else if (ResearchStates.isCancelled(data.status)) {
                    if (progressText) progressText.textContent = 'Indexing was cancelled.';
                }

                setTimeout(() => {
                    if (progressDiv) progressDiv.style.display = 'none';
                    if (progressText) progressText.style.color = '';
                    loadIndexingStatus();
                    if (indexBtn) {
                        indexBtn.disabled = false;
                        indexBtn.innerHTML = '<i class="fas fa-sync"></i> Index All';
                    }
                }, 2000);
            }
        } catch (error) {
            SafeLogger.error('Error polling indexing status:', error);
            pollErrorCount++;
            if (pollErrorCount >= 5) {
                clearInterval(indexingPollInterval);
                indexingPollInterval = null;
                isIndexing = false;
                if (progressText) {
                    progressText.textContent = 'Lost connection to server. Please try again.';
                    progressText.style.color = 'var(--error-color)';
                }
                if (indexBtn) {
                    indexBtn.disabled = false;
                    indexBtn.innerHTML = '<i class="fas fa-sync"></i> Index All';
                }
            }
        }
    }, 2000);
}

/**
 * Check if indexing is already in progress on page load and resume UI
 */
async function checkAndResumeIndexing() {
    if (!cachedCollectionId) return;

    try {
        const response = await fetch(URLBuilder.build(URLS.LIBRARY_API.COLLECTION_INDEX_STATUS, cachedCollectionId));
        if (!response.ok) {
            SafeLogger.warn('Index status check returned ' + response.status);
            return;
        }
        const data = await response.json();

        if (data.status === 'processing') {
            SafeLogger.log('Active indexing task found, resuming UI');
            const indexBtn = document.getElementById('index-all-btn');
            const progressDiv = document.getElementById('indexing-progress');
            const progressBar = document.getElementById('indexing-progress-bar');
            const progressText = document.getElementById('indexing-progress-text');

            isIndexing = true;
            if (indexBtn) {
                indexBtn.disabled = true;
                indexBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Indexing...';
            }
            if (progressDiv) progressDiv.style.display = 'block';
            if (progressBar) progressBar.style.width = '0%';
            if (progressText) progressText.style.color = '';

            // Apply current progress immediately
            if (data.progress_total > 0) {
                const percent = Math.round((data.progress_current / data.progress_total) * 100);
                if (progressBar) progressBar.style.width = percent + '%';
            }
            if (data.progress_message && progressText) {
                progressText.textContent = data.progress_message;
            }

            startPolling();
        }
    } catch (error) {
        SafeLogger.error('Error checking indexing status:', error);
    }
}

/**
 * Perform semantic search against the generic collection search endpoint.
 * Called from history.js when in semantic mode.
 *
 * @param {string} query - Search query
 * @returns {Promise<Array>} Search results
 */
async function semanticSearchHistory(query) {
    if (!query) return [];

    // Use cached collection ID, or fetch it
    if (!cachedCollectionId) {
        await loadIndexingStatus();
    }
    if (!cachedCollectionId) {
        return { needsIndexing: true };
    }

    const csrfToken = (window.api && window.api.getCsrfToken)
        ? window.api.getCsrfToken()
        : (document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '');

    const response = await fetch(URLBuilder.build(URLS.LIBRARY_API.COLLECTION_SEARCH, cachedCollectionId), {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': csrfToken,
        },
        body: JSON.stringify({ query, limit: 20 }),
    });

    if (!response.ok) {
        if (response.status === 404) {
            // Cache is invalid (collection deleted server-side); clear so the
            // next call re-fetches. Single-writer pattern, no race.
            // eslint-disable-next-line require-atomic-updates
            cachedCollectionId = null;
        }
        throw new Error(`Server returned ${response.status}`);
    }
    const data = await response.json();

    if (!data.success) {
        throw new Error(data.error || 'Search failed');
    }

    return data.results || [];
}

/**
 * Render semantic search results into the history-items container.
 * Uses shared createSemanticResultCard from semantic_search.js.
 */
function renderSemanticResults(results, query) {
    const container = document.getElementById('history-items');

    if (!container) return;

    if (!results || results.length === 0) {
        container.innerHTML = `
            <div class="ldr-empty-state">
                <i class="fas fa-search"></i>
                <p>No matching results found. Try indexing more research or using different keywords.</p>
            </div>
        `;
        return;
    }

    const fragment = document.createDocumentFragment();
    for (const result of results) {
        if (window.SemanticSearch && window.SemanticSearch.createSemanticResultCard) {
            fragment.appendChild(window.SemanticSearch.createSemanticResultCard(result, null, query));
        }
    }
    container.innerHTML = '';
    container.appendChild(fragment);
}

/**
 * Return the cached collection ID (or null if not indexed).
 * Used by history.js hybrid mode to check indexing status.
 */
function getSemanticCollectionId() {
    return cachedCollectionId;
}

// Expose functions needed by history.js under a single namespace
window.HistorySearch = {
    toggleSemanticPanel,
    triggerIndexing,
    semanticSearchHistory,
    renderSemanticResults,
    getSemanticCollectionId,
};

/**
 * Set up event listeners for panel header and index button
 */
function setupEventListeners() {
    const header = document.getElementById('semantic-panel-header');
    if (header) {
        header.addEventListener('click', toggleSemanticPanel);
        header.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                toggleSemanticPanel();
            }
        });
    }

    const indexBtn = document.getElementById('index-all-btn');
    if (indexBtn) {
        indexBtn.addEventListener('click', triggerIndexing);
    }
}

// Clean up polling interval on page unload
window.addEventListener('beforeunload', () => {
    if (indexingPollInterval) {
        clearInterval(indexingPollInterval);
        indexingPollInterval = null;
    }
});

// Initialize on page load
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => {
        setupEventListeners();
        initSemanticSearch();
    });
} else {
    setupEventListeners();
    initSemanticSearch();
}

})();
