/**
 * Collection Details Page JavaScript
 * Handles individual collection management and document indexing
 */

let collectionData = null;
let documentsData = [];
let currentFilter = 'all';
let indexingPollInterval = null;

// safeFetch (with URLValidator) is now provided by utils/safe-fetch.js loaded in base.html

/**
 * Initialize the page
 */
document.addEventListener('DOMContentLoaded', function() {
    loadCollectionDetails();

    // Setup button handlers
    document.getElementById('index-collection-btn').addEventListener('click', () => indexCollection(false));
    document.getElementById('reindex-collection-btn').addEventListener('click', () => indexCollection(true));
    document.getElementById('delete-collection-btn').addEventListener('click', deleteCollection);
    document.getElementById('cancel-indexing-btn').addEventListener('click', cancelIndexing);

    // Check if there's an active indexing task
    checkAndResumeIndexing();
});

/**
 * Load collection details and documents
 */
async function loadCollectionDetails() {
    try {
        const response = await safeFetch(URLBuilder.build(URLS.LIBRARY_API.COLLECTION_DOCUMENTS, COLLECTION_ID));
        const data = await response.json();

        if (data.success) {
            collectionData = data.collection;
            documentsData = data.documents || [];

            // Update header
            document.getElementById('collection-name').textContent = collectionData.name;
            document.getElementById('collection-description').textContent = collectionData.description || '';

            // Update statistics
            updateStatistics();

            // Display collection's embedding settings
            displayCollectionEmbeddingSettings();

            // Render documents
            renderDocuments();

            // Show search section if any documents are indexed
            initCollectionSearch();
        } else {
            showError('Failed to load collection details: ' + data.error);
        }
    } catch (error) {
        SafeLogger.error('Error loading collection details:', error);
        showError('Failed to load collection details');
    }
}

/**
 * Update statistics
 */
function updateStatistics() {
    const totalDocs = documentsData.length;
    const indexedDocs = documentsData.filter(doc => doc.indexed).length;
    const unindexedDocs = totalDocs - indexedDocs;
    const totalChunks = documentsData.reduce((sum, doc) => sum + (doc.chunk_count || 0), 0);

    document.getElementById('stat-total-docs').textContent = totalDocs;
    document.getElementById('stat-indexed-docs').textContent = indexedDocs;
    document.getElementById('stat-unindexed-docs').textContent = unindexedDocs;
    document.getElementById('stat-total-chunks').textContent = totalChunks;
}

/**
 * Display collection's embedding settings
 */
function displayCollectionEmbeddingSettings() {
    const infoContainer = document.getElementById('collection-embedding-info');

    if (collectionData.embedding_model) {
        // Collection has stored settings - display them
        // 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
        infoContainer.innerHTML = `
            <div class="ldr-info-item">
                <span class="ldr-info-label">Provider:</span>
                <span class="ldr-info-value">${escapeHtml(getProviderLabel(collectionData.embedding_model_type))}</span>
            </div>
            <div class="ldr-info-item">
                <span class="ldr-info-label">Model:</span>
                <span class="ldr-info-value">${escapeHtml(collectionData.embedding_model)}</span>
            </div>
            <div class="ldr-info-item">
                <span class="ldr-info-label">Chunk Size:</span>
                <span class="ldr-info-value">${escapeHtml(String(collectionData.chunk_size || 'Not set'))} ${collectionData.chunk_size ? 'characters' : ''}</span>
            </div>
            <div class="ldr-info-item">
                <span class="ldr-info-label">Chunk Overlap:</span>
                <span class="ldr-info-value">${escapeHtml(String(collectionData.chunk_overlap || 'Not set'))} ${collectionData.chunk_overlap ? 'characters' : ''}</span>
            </div>
            ${collectionData.embedding_dimension ? `
            <div class="ldr-info-item">
                <span class="ldr-info-label">Embedding Dimension:</span>
                <span class="ldr-info-value">${escapeHtml(String(collectionData.embedding_dimension))}</span>
            </div>
            ` : ''}
            ${collectionData.splitter_type ? `
            <div class="ldr-info-item">
                <span class="ldr-info-label">Splitter Type:</span>
                <span class="ldr-info-value">${escapeHtml(collectionData.splitter_type)}</span>
            </div>
            ` : ''}
            ${collectionData.distance_metric ? `
            <div class="ldr-info-item">
                <span class="ldr-info-label">Distance Metric:</span>
                <span class="ldr-info-value">${escapeHtml(collectionData.distance_metric)}</span>
            </div>
            ` : ''}
            ${collectionData.index_type ? `
            <div class="ldr-info-item">
                <span class="ldr-info-label">Index Type:</span>
                <span class="ldr-info-value">${escapeHtml(collectionData.index_type)}</span>
            </div>
            ` : ''}
            ${collectionData.normalize_vectors !== null && collectionData.normalize_vectors !== undefined ? `
            <div class="ldr-info-item">
                <span class="ldr-info-label">Normalize Vectors:</span>
                <span class="ldr-info-value">${collectionData.normalize_vectors ? 'Yes' : 'No'}</span>
            </div>
            ` : ''}
            ${collectionData.index_file_size ? `
            <div class="ldr-info-item">
                <span class="ldr-info-label">Index File Size:</span>
                <span class="ldr-info-value">${escapeHtml(String(collectionData.index_file_size))}</span>
            </div>
            ` : ''}
        `;
    } else {
        // Collection not yet indexed - no settings stored
        infoContainer.innerHTML = `
            <div class="ldr-alert ldr-alert-info">
                <i class="fas fa-info-circle"></i> This collection hasn't been indexed yet. Settings will be stored when you index documents.
            </div>
        `;
    }
}

/**
 * Get provider label (simplified version)
 */
function getProviderLabel(providerValue) {
    const providerMap = {
        'sentence_transformers': 'Sentence Transformers',
        'ollama': 'Ollama',
        'openai': 'OpenAI',
        'anthropic': 'Anthropic',
        'cohere': 'Cohere'
    };
    return providerMap[providerValue] || providerValue || 'Not configured';
}

/**
 * Get model label (simplified version)
 */
function getModelLabel(modelValue, provider) {
    if (!modelValue) return 'Not configured';
    if (provider === 'ollama' && modelValue.includes(':')) {
        return modelValue.split(':')[0];
    }
    return modelValue;
}

/**
 * Render documents list
 */
function renderDocuments() {
    const container = document.getElementById('documents-list');
    const noDocsMessage = document.getElementById('no-documents-message');

    // Filter documents based on current filter
    let filteredDocs = documentsData;
    if (currentFilter === 'indexed') {
        filteredDocs = documentsData.filter(doc => doc.indexed);
    } else if (currentFilter === 'unindexed') {
        filteredDocs = documentsData.filter(doc => !doc.indexed);
    }

    if (filteredDocs.length === 0) {
        container.style.display = 'none';
        noDocsMessage.style.display = 'flex';
        return;
    }

    container.style.display = 'block';
    noDocsMessage.style.display = 'none';

    // eslint-disable-next-line no-unsanitized/property -- audited 2026-03-28: all interpolations use escapeHtml/esc, numeric coercion, or hardcoded strings
    container.innerHTML = filteredDocs.map(doc => `
        <div class="ldr-document-item ${doc.indexed ? 'indexed' : 'unindexed'}">
            <a href="/library/document/${encodeURIComponent(doc.id)}" class="ldr-document-link" style="text-decoration: none; color: inherit; display: block; flex: 1;">
                <div class="ldr-document-info">
                    <div class="ldr-document-title">
                        ${escapeHtml(doc.filename)}
                        ${doc.has_pdf ? '<i class="fas fa-file-pdf" style="color: var(--error-color); margin-left: 8px;" title="PDF stored"></i>' : ''}
                        ${doc.has_text_db ? '<i class="fas fa-file-alt" style="color: var(--success-color); margin-left: 8px;" title="Text content available"></i>' : ''}
                        ${doc.in_other_collections ? `<i class="fas fa-link" style="color: var(--accent-primary); margin-left: 8px;" title="In ${escapeHtml(String(doc.other_collections_count + 1))} collections"></i>` : ''}
                    </div>
                    <div class="ldr-document-meta">
                        ${doc.file_size ? `Size: ${formatBytes(doc.file_size)} • ` : ''}
                        ${doc.source_type && doc.source_type !== 'unknown' ? `<span class="ldr-badge ldr-badge-info">${escapeHtml(doc.source_type.replace('_', ' '))}</span> • ` : ''}
                        ${doc.indexed ?
                            `<span class="ldr-badge ldr-badge-success">Indexed (${escapeHtml(String(doc.chunk_count))} chunks)</span>` :
                            '<span class="ldr-badge ldr-badge-warning">Not indexed</span>'
                        }
                        ${doc.last_indexed_at ? ` • Last indexed: ${escapeHtml(new Date(doc.last_indexed_at).toLocaleString())}` : ''}
                    </div>
                </div>
            </a>
            <div class="ldr-document-actions">
                <button class="ldr-btn-remove-from-collection" onclick="event.stopPropagation(); removeDocumentFromCollection('${escapeHtml(doc.id)}')"
                        title="Remove from collection. ${doc.in_other_collections ? 'Document exists in other collections.' : 'Document will be deleted (not in other collections).'}">
                    <i class="fas fa-unlink"></i>
                </button>
                <button class="ldr-btn-delete-doc" onclick="event.stopPropagation(); deleteDocumentCompletely('${escapeHtml(doc.id)}')"
                        title="Permanently delete this document, including PDF and text content. This cannot be undone.">
                    <i class="fas fa-trash"></i>
                </button>
            </div>
        </div>
    `).join('');
}

/**
 * Filter documents
 */
function filterDocuments(filter) {
    currentFilter = filter;

    // Update button states
    document.querySelectorAll('.ldr-filter-controls .ldr-btn-collections').forEach(btn => {
        btn.classList.remove('ldr-active');
    });
    event.target.classList.add('ldr-active');

    renderDocuments();
}


/**
 * Index collection documents (background indexing)
 */
async function indexCollection(forceReindex) {
    SafeLogger.log('Index Collection button clicked, force_reindex:', forceReindex);

    const action = forceReindex ? 're-index' : 'index';
    if (!confirm(`${action.charAt(0).toUpperCase() + action.slice(1)} all documents in this collection?`)) {
        return;
    }

    try {
        const csrfToken = window.api ? window.api.getCsrfToken() : '';

        // Start background indexing
        const response = await safeFetch(`/library/api/collections/${COLLECTION_ID}/index/start`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({ force_reindex: forceReindex })
        });

        const data = await response.json();

        if (!data.success) {
            if (response.status === 409) {
                // Already indexing
                showError(data.error || 'Indexing is already in progress');
                showProgressUI();
                startPolling();
            } else {
                showError(data.error || 'Failed to start indexing');
            }
            return;
        }

        SafeLogger.log('Background indexing started, task_id:', data.task_id);

        // Show progress UI and start polling
        showProgressUI();
        addLogEntry('Indexing started in background...', 'info');
        startPolling();

    } catch (error) {
        SafeLogger.error('Error starting indexing:', error);
        showError('Failed to start indexing');
    }
}

/**
 * Check if there's an active indexing task and resume UI
 */
async function checkAndResumeIndexing() {
    try {
        const response = await safeFetch(`/library/api/collections/${COLLECTION_ID}/index/status`);
        const data = await response.json();

        if (data.status === 'processing') {
            SafeLogger.log('Active indexing task found, resuming UI');
            showProgressUI();
            updateProgressFromStatus(data);
            startPolling();
        }
    } catch (error) {
        SafeLogger.error('Error checking indexing status:', error);
    }
}

/**
 * Show the progress UI
 */
function showProgressUI() {
    const progressSection = document.getElementById('indexing-progress');
    const cancelBtn = document.getElementById('cancel-indexing-btn');
    const indexBtn = document.getElementById('index-collection-btn');
    const reindexBtn = document.getElementById('reindex-collection-btn');

    progressSection.style.display = 'block';
    cancelBtn.style.display = 'inline-block';
    indexBtn.disabled = true;
    reindexBtn.disabled = true;
}

/**
 * Hide the progress UI
 */
function hideProgressUI() {
    const progressSection = document.getElementById('indexing-progress');
    const cancelBtn = document.getElementById('cancel-indexing-btn');
    const indexBtn = document.getElementById('index-collection-btn');
    const reindexBtn = document.getElementById('reindex-collection-btn');
    const spinner = document.getElementById('indexing-spinner');

    cancelBtn.style.display = 'none';
    indexBtn.disabled = false;
    reindexBtn.disabled = false;

    // Keep progress visible for a few seconds before hiding
    setTimeout(() => {
        progressSection.style.display = 'none';
    }, 5000);
}

/**
 * Start polling for indexing status
 */
function startPolling() {
    // Clear any existing interval
    if (indexingPollInterval) {
        clearInterval(indexingPollInterval);
    }

    // Poll every 2 seconds
    indexingPollInterval = setInterval(async () => {
        try {
            const response = await safeFetch(`/library/api/collections/${COLLECTION_ID}/index/status`);
            const data = await response.json();

            updateProgressFromStatus(data);

            // Stop polling if indexing is done
            if (ResearchStates.isTerminal(data.status) || data.status === 'idle') {
                clearInterval(indexingPollInterval);
                indexingPollInterval = null;

                if (ResearchStates.isCompleted(data.status)) {
                    addLogEntry(data.progress_message || 'Indexing completed!', 'success');
                } else if (ResearchStates.isFailed(data.status)) {
                    addLogEntry(`Indexing failed: ${data.error_message || 'Unknown error'}`, 'error');
                } else if (ResearchStates.isCancelled(data.status)) {
                    addLogEntry('Indexing was cancelled', 'warning');
                }

                hideProgressUI();
                loadCollectionDetails();
            }
        } catch (error) {
            SafeLogger.error('Error polling status:', error);
        }
    }, 2000);
}

/**
 * Update progress UI from status data
 */
function updateProgressFromStatus(data) {
    const progressFill = document.getElementById('progress-fill');
    const progressText = document.getElementById('progress-text');

    if (data.progress_total > 0) {
        const percent = Math.round((data.progress_current / data.progress_total) * 100);
        progressFill.style.width = percent + '%';
    }

    if (data.progress_message) {
        progressText.textContent = data.progress_message;
    }
}

/**
 * Cancel indexing
 */
async function cancelIndexing() {
    if (!confirm('Cancel the current indexing operation?')) {
        return;
    }

    try {
        const csrfToken = window.api ? window.api.getCsrfToken() : '';

        const response = await safeFetch(`/library/api/collections/${COLLECTION_ID}/index/cancel`, {
            method: 'POST',
            headers: {
                'X-CSRFToken': csrfToken
            }
        });

        const data = await response.json();

        if (data.success) {
            const progressText = document.getElementById('progress-text');
            progressText.textContent = 'Cancelling...';
            addLogEntry('Cancellation requested...', 'warning');
        } else {
            showError(data.error || 'Failed to cancel indexing');
        }
    } catch (error) {
        SafeLogger.error('Error cancelling indexing:', error);
        showError('Failed to cancel indexing');
    }
}

/**
 * Add log entry to progress log
 */
function addLogEntry(message, type = 'info') {
    const progressLog = document.getElementById('progress-log');
    const entry = document.createElement('div');
    entry.className = `ldr-log-entry ldr-log-${type}`;
    entry.textContent = message;
    progressLog.appendChild(entry);
    progressLog.scrollTop = progressLog.scrollHeight;
}

/**
 * Delete collection
 */
async function deleteCollection() {
    if (!confirm(`Are you sure you want to delete "${collectionData.name}"? This action cannot be undone.`)) return;

    try {
        const csrfToken = window.api ? window.api.getCsrfToken() : '';
        const response = await safeFetch(URLBuilder.build(URLS.LIBRARY_API.COLLECTION_DETAILS, COLLECTION_ID), {
            method: 'DELETE',
            headers: {
                'X-CSRFToken': csrfToken
            }
        });

        const data = await response.json();
        if (data.success) {
            showSuccess(`Collection "${collectionData.name}" deleted successfully`);
            // Redirect to collections page
            setTimeout(() => {
                window.location.href = '/library/collections';
            }, 1000);
        } else {
            showError('Failed to delete collection: ' + data.error);
        }
    } catch (error) {
        SafeLogger.error('Error deleting collection:', error);
        showError('Failed to delete collection');
    }
}

/**
 * Format bytes to human readable
 */
function formatBytes(bytes) {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
}

// Prefer the full escapeHtml from xss-protection.js; inline fallback if it hasn't loaded yet
// bearer:disable javascript_lang_manual_html_sanitization
var escapeHtml = window.escapeHtml || function(str) {
    return String(str).replace(/[&<>"']/g, function(m) {
        return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m];
    });
};


/**
 * Show success message
 */
function showSuccess(message) {
    alert('Success: ' + message);
}

/**
 * Show error message
 */
function showError(message) {
    alert('Error: ' + message);
}

/**
 * Remove document from this collection
 * If not in other collections, the document will be deleted
 */
async function removeDocumentFromCollection(documentId) {
    // Check if DeleteManager is available
    if (typeof DeleteManager !== 'undefined' && DeleteManager.removeFromCollection) {
        DeleteManager.removeFromCollection(documentId, COLLECTION_ID, {
            onSuccess: () => loadCollectionDetails()
        });
    } else {
        // Fallback to simple confirm
        if (!confirm('Remove this document from the collection? If not in other collections, it will be deleted.')) {
            return;
        }

        try {
            const csrfToken = window.api ? window.api.getCsrfToken() : '';
            const response = await fetch(`/library/api/collection/${COLLECTION_ID}/document/${documentId}`, {
                method: 'DELETE',
                headers: {
                    'X-CSRFToken': csrfToken
                }
            });

            const data = await response.json();
            if (data.success) {
                const message = data.document_deleted
                    ? 'Document removed and deleted (not in other collections)'
                    : 'Document removed from collection';
                showSuccess(message);
                loadCollectionDetails();
            } else {
                showError('Failed to remove document: ' + data.error);
            }
        } catch (error) {
            SafeLogger.error('Error removing document:', error);
            showError('Failed to remove document');
        }
    }
}

/**
 * Delete document completely (from all collections)
 */
async function deleteDocumentCompletely(documentId) {
    // Check if DeleteManager is available
    if (typeof DeleteManager !== 'undefined' && DeleteManager.deleteDocument) {
        DeleteManager.deleteDocument(documentId, {
            onSuccess: () => loadCollectionDetails()
        });
    } else {
        // Fallback to simple confirm
        if (!confirm('Permanently delete this document? This cannot be undone.')) {
            return;
        }

        try {
            const csrfToken = window.api ? window.api.getCsrfToken() : '';
            const response = await fetch(`/library/api/document/${documentId}`, {
                method: 'DELETE',
                headers: {
                    'X-CSRFToken': csrfToken
                }
            });

            const data = await response.json();
            if (data.success) {
                showSuccess('Document deleted successfully');
                loadCollectionDetails();
            } else {
                showError('Failed to delete document: ' + data.error);
            }
        } catch (error) {
            SafeLogger.error('Error deleting document:', error);
            showError('Failed to delete document');
        }
    }
}

// =============================================================================
// Collection Semantic Search
// =============================================================================

let searchDebounceTimer = null;
let searchListenersAttached = false;
let collectionSearchId = 0;

/**
 * Initialize search section if collection has indexed documents.
 */
function initCollectionSearch() {
    const hasIndexed = documentsData.some(function(d) { return d.indexed; });
    const section = document.getElementById('collection-search-section');
    if (!section) return;

    if (hasIndexed) {
        section.style.display = 'block';

        // Only attach listeners once to avoid duplicates on repeated loadCollectionDetails() calls
        if (!searchListenersAttached) {
            searchListenersAttached = true;
            const searchBtn = document.getElementById('collection-search-btn');
            const searchInput = document.getElementById('collection-search-input');

            if (searchBtn) {
                searchBtn.addEventListener('click', function() {
                    const query = searchInput ? searchInput.value.trim() : '';
                    if (query) searchCollection(query);
                });
            }
            if (searchInput) {
                searchInput.addEventListener('keydown', function(e) {
                    if (e.key === 'Enter') {
                        e.preventDefault();
                        const query = searchInput.value.trim();
                        if (query) searchCollection(query);
                    }
                });
                searchInput.addEventListener('input', function() {
                    clearTimeout(searchDebounceTimer);
                    const query = searchInput.value.trim();
                    if (!query) {
                        const container = document.getElementById('collection-search-results');
                        if (container) container.innerHTML = '';
                        return;
                    }
                    searchDebounceTimer = setTimeout(function() {
                        searchCollection(query);
                    }, 500);
                });
            }
        }
    }
}

/**
 * Search the collection semantically.
 */
async function searchCollection(query) {
    var container = document.getElementById('collection-search-results');
    if (!container) return;

    var currentSearchId = ++collectionSearchId;

    // Show loading
    // bearer:disable javascript_lang_dangerous_insert_html
    container.innerHTML = '<div class="ldr-hybrid-loading"><div class="ldr-spinner" style="width:16px;height:16px;border-width:2px;"></div> Searching...</div>';

    try {
        // Reuse LibrarySearch module for the API call
        if (!window.LibrarySearch || !window.LibrarySearch.performSemanticSearch) {
            // bearer:disable javascript_lang_dangerous_insert_html
            container.innerHTML = '<div class="ldr-empty-state"><p>Search module not loaded. Please refresh.</p></div>';
            return;
        }

        var data = await window.LibrarySearch.performSemanticSearch(COLLECTION_ID, query, 20);

        // Discard stale results if a newer search was initiated
        if (currentSearchId !== collectionSearchId) return;

        if (data.success && data.results) {
            if (data.results.length === 0) {
                // bearer:disable javascript_lang_dangerous_insert_html
                container.innerHTML = '<div class="ldr-empty-state"><i class="fas fa-search fa-2x"></i><p>No matching results found.</p></div>';
                return;
            }

            var cardConfig = window.LibrarySearch.getLibraryCardConfig
                ? window.LibrarySearch.getLibraryCardConfig()
                : undefined;
            var createCard = window.SemanticSearch && window.SemanticSearch.createSemanticResultCard;

            if (createCard) {
                var fragment = document.createDocumentFragment();
                for (var i = 0; i < data.results.length; i++) {
                    fragment.appendChild(createCard(data.results[i], cardConfig, query));
                }
                container.innerHTML = '';
                container.appendChild(fragment);
            } else {
                // bearer:disable javascript_lang_dangerous_insert_html
                container.innerHTML = '<div class="ldr-empty-state"><p>Semantic search module not loaded.</p></div>';
            }
        } else {
            // bearer:disable javascript_lang_dangerous_insert_html
            container.innerHTML = '<div class="ldr-empty-state"><i class="fas fa-exclamation-triangle fa-2x"></i><p>' + escapeHtml(data.error || 'Search failed') + '</p></div>';
        }
    } catch (error) {
        SafeLogger.error('Collection search error:', error);
        // bearer:disable javascript_lang_dangerous_insert_html
        container.innerHTML = '<div class="ldr-empty-state"><i class="fas fa-exclamation-triangle fa-2x"></i><p>Search failed. Please try again.</p></div>';
    }
}
