/**
 * Unified Search Manager
 * Manages the combined documentation and map search functionality
 */

import { MkDocsSearch } from './mkdocs-search.js';
import mapSearch from './map-search.js';
import databaseSearch from './database-search.js';
import { currentUser } from './auth.js';

export class UnifiedSearchManager {
    constructor(config = {}) {
        this.mode = 'docs'; // 'docs', 'map', or 'database'
        this.mkdocsSearch = null;
        this.mapSearch = mapSearch;
        this.databaseSearch = databaseSearch; // Add this line
        this.debounceTimeout = null;
        this.config = config;
        
        // DOM elements
        this.container = null;
        this.searchInput = null;
        this.searchResults = null;
        this.modeButtons = null;
        this.resultsHeader = null;
        this.resultsList = null;
        this.closeButton = null;
        
        this.isInitialized = false;
    }

    /**
     * Initialize the unified search
     * @returns {Promise<boolean>} Success status
     */
    async initialize() {
        try {
            console.log('Initializing Unified Search Manager...');
            
            // Initialize MkDocs search
            this.mkdocsSearch = new MkDocsSearch(this.config);
            const mkdocsInitialized = await this.mkdocsSearch.initialize();
            
            if (!mkdocsInitialized) {
                console.warn('MkDocs search could not be initialized');
            }
            
            this.isInitialized = true;
            console.log('Unified Search Manager initialized successfully');
            return true;
            
        } catch (error) {
            console.error('Failed to initialize Unified Search Manager:', error);
            return false;
        }
    }

    /**
     * Bind the search to DOM elements
     * @param {HTMLElement} container - The search container element
     */
    bindToElements(container) {
        this.container = container;
        this.searchInput = container.querySelector('.unified-search-input');
        this.searchResults = container.querySelector('.unified-search-results');
        this.modeButtons = container.querySelectorAll('.search-mode-btn');
        this.resultsHeader = container.querySelector('.unified-search-results-header');
        this.resultsList = container.querySelector('.unified-search-results-list');
        this.closeButton = container.querySelector('.close-results');

        if (!this.searchInput || !this.searchResults) {
            console.error('Required search elements not found');
            return false;
        }

        // Hide database search option for temp users
        if (currentUser?.userType === 'temp') {
            const databaseModeBtn = container.querySelector('[data-mode="database"]');
            if (databaseModeBtn) {
                databaseModeBtn.style.display = 'none';
            }
        }

        this.setupEventListeners();
        this.updatePlaceholder();
        return true;
    }

    /**
     * Set up event listeners
     */
    setupEventListeners() {
        // Search input events
        this.searchInput.addEventListener('input', (e) => {
            this.handleSearchInput(e.target.value);
        });

        this.searchInput.addEventListener('keydown', (e) => {
            this.handleKeyDown(e);
        });

        this.searchInput.addEventListener('focus', () => {
            if (this.searchInput.value.trim()) {
                this.showResults();
            }
            // Prevent zoom on mobile iOS
            if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
                this.searchInput.style.fontSize = '16px';
            }
        });

        this.searchInput.addEventListener('blur', () => {
            // Small delay to allow clicking on results
            setTimeout(() => {
                // Only hide if not clicking within search container
                if (!this.container.matches(':hover')) {
                    // this.hideResults();
                }
            }, 150);
        });

        // Mode toggle buttons
        this.modeButtons.forEach(btn => {
            btn.addEventListener('click', () => {
                const mode = btn.dataset.mode;
                if (mode && mode !== this.mode) {
                    this.setMode(mode);
                }
            });
        });

        // Close button
        if (this.closeButton) {
            this.closeButton.addEventListener('click', () => {
                this.hideResults();
            });
        }

        // Global keyboard shortcuts
        document.addEventListener('keydown', (e) => {
            // Ctrl+K to focus search
            if (e.ctrlKey && e.key === 'k') {
                e.preventDefault();
                this.focusSearch();
            }
            
            // Ctrl+Shift+D for docs mode
            if (e.ctrlKey && e.shiftKey && e.key === 'D') {
                e.preventDefault();
                this.setMode('docs');
                this.focusSearch();
            }
            
            // Ctrl+Shift+M for map mode
            if (e.ctrlKey && e.shiftKey && e.key === 'M') {
                e.preventDefault();
                this.setMode('map');
                this.focusSearch();
            }

            // Ctrl+Shift+B for database mode
            if (e.ctrlKey && e.shiftKey && e.key === 'B') {
                e.preventDefault();
                this.setMode('database');
                this.focusSearch();
            }
            
            // Escape to close results
            if (e.key === 'Escape') {
                this.hideResults();
            }
        });

        // Click outside to close results
        document.addEventListener('click', (e) => {
            if (!this.container.contains(e.target)) {
                this.hideResults();
            }
        });

        // Touch events for mobile
        document.addEventListener('touchstart', (e) => {
            if (!this.container.contains(e.target)) {
                this.hideResults();
            }
        });
    }

    /**
     * Set the search mode
     * @param {string} mode - 'docs' or 'map'
     */
    setMode(mode) {
        if (mode !== 'docs' && mode !== 'map' && mode !== 'database') {
            console.error('Invalid search mode:', mode);
            return;
        }

        // Prevent database search for temp users
        if (currentUser?.userType === 'temp' && mode === 'database') {
            console.log('Database search not available for temporary users');
            this.showError('Database search is not available for temporary users');
            return;
        }

        this.mode = mode;
        
        // Update button states
        this.modeButtons.forEach(btn => {
            btn.classList.toggle('active', btn.dataset.mode === mode);
        });

        this.updatePlaceholder();
        this.clearResults();
        
        // If there's a current search, re-run it in the new mode
        const currentQuery = this.searchInput.value.trim();
        if (currentQuery) {
            this.handleSearchInput(currentQuery);
        }

        console.log('Search mode changed to:', mode);
    }

    /**
     * Update the search input placeholder
     */
    updatePlaceholder() {
        if (!this.searchInput) return;
        
        const placeholders = {
            docs: 'Search documentation... (Ctrl+K)',
            map: 'Search addresses... (Ctrl+K)',
            database: 'Search locations... (Ctrl+K)'
        };
        
        this.searchInput.placeholder = placeholders[this.mode] || 'Search...';
    }

    /**
     * Handle search input
     * @param {string} query - Search query
     */
    handleSearchInput(query) {
        // Clear previous debounce
        if (this.debounceTimeout) {
            clearTimeout(this.debounceTimeout);
        }

        // Debounce the search
        this.debounceTimeout = setTimeout(() => {
            this.performSearch(query);
        }, 300);
    }

    /**
     * Perform the actual search
     * @param {string} query - Search query
     */
    async performSearch(query) {
        const trimmedQuery = query.trim();
        
        if (!trimmedQuery) {
            this.clearResults();
            return;
        }

        if (trimmedQuery.length < 2) {
            this.clearResults();
            return;
        }

        try {
            this.showLoading();

            let results = [];
            
            if (this.mode === 'docs' && this.mkdocsSearch) {
                results = await this.mkdocsSearch.search(trimmedQuery);
            } else if (this.mode === 'map') {
                results = await this.mapSearch.search(trimmedQuery);
            } else if (this.mode === 'database') {
                results = await this.databaseSearch.search(trimmedQuery);
            }

            this.displayResults(results, trimmedQuery);

        } catch (error) {
            console.error('Search error:', error);
            this.showError(error.message);
        }
    }

    /**
     * Display search results
     * @param {Array} results - Search results
     * @param {string} query - Original query
     */
    displayResults(results, query) {
        if (!this.resultsList) return;

        this.resultsList.innerHTML = '';

        if (results.length === 0) {
            this.showNoResults();
            return;
        }

        // Update results count
        this.updateResultsCount(results.length, query);

        // Create result elements
        results.forEach(result => {
            let resultEl;
            
            if (this.mode === 'docs') {
                resultEl = this.createDocsResultElement(result);
            } else if (this.mode === 'map') {
                resultEl = this.mapSearch.createResultElement(result);
            } else if (this.mode === 'database') {
                resultEl = this.databaseSearch.createResultElement(result);
            }

            if (resultEl) {
                this.resultsList.appendChild(resultEl);
            }
        });

        this.showResults();
    }

    /**
     * Create a documentation search result element
     * @param {Object} result - Search result
     * @returns {HTMLElement} Result element
     */
    createDocsResultElement(result) {
        const resultEl = document.createElement('div');
        resultEl.className = 'search-result-item search-result-docs';
        
        resultEl.innerHTML = `
            <a href="${result.url || '#'}" class="search-result-link" target="_blank" rel="noopener">
                <div class="result-title">${result.title || 'Untitled'}</div>
                <div class="result-excerpt">${result.snippet || result.excerpt || ''}</div>
                <div class="result-path">${result.location || result.path || ''}</div>
            </a>
            <button class="btn btn-sm btn-secondary make-qr-btn" data-url="${result.url || '#'}" title="Generate QR Code">
                <span class="btn-icon">📱</span>
                <span class="btn-text">QR</span>
            </button>
        `;

        // Add QR button event listener
        const qrButton = resultEl.querySelector('.make-qr-btn');
        qrButton.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            const url = qrButton.getAttribute('data-url');
            this.showQRCodeModal(url);
        });

        // Add click handler to hide results when link is clicked
        const link = resultEl.querySelector('.search-result-link');
        link.addEventListener('click', () => {
            this.hideResults();
        });

        return resultEl;
    }

    /**
     * Show loading state
     */
    showLoading() {
        if (!this.resultsList) return;
        
        this.resultsList.innerHTML = `
            <div class="search-loading">
                Searching...
            </div>
        `;
        
        this.showResults();
    }

    /**
     * Show no results message
     */
    showNoResults() {
        if (!this.resultsList) return;
        
        this.resultsList.innerHTML = `
            <div class="search-no-results">
                No results found for "${this.searchInput.value.trim()}"
            </div>
        `;
        
        this.updateResultsCount(0);
        this.showResults();
    }

    /**
     * Show error message
     * @param {string} message - Error message
     */
    showError(message) {
        if (!this.resultsList) return;
        
        this.resultsList.innerHTML = `
            <div class="search-no-results">
                Error: ${message}
            </div>
        `;
        
        this.showResults();
    }

    /**
     * Update results count display
     * @param {number} count - Number of results
     * @param {string} query - Search query
     */
    updateResultsCount(count, query = '') {
        if (!this.resultsHeader) return;
        
        const countEl = this.resultsHeader.querySelector('.results-count');
        if (countEl) {
            if (count === 0) {
                countEl.textContent = 'No results';
            } else if (count === 1) {
                countEl.textContent = '1 result';
            } else {
                countEl.textContent = `${count} results`;
            }
        }
    }

    /**
     * Show search results
     */
    showResults() {
        if (this.searchResults) {
            this.searchResults.classList.remove('hidden');
        }
    }

    /**
     * Hide search results
     */
    hideResults() {
        if (this.searchResults) {
            this.searchResults.classList.add('hidden');
        }
    }

    /**
     * Clear search results
     */
    clearResults() {
        if (this.resultsList) {
            this.resultsList.innerHTML = '';
        }
        this.hideResults();
    }

    /**
     * Focus the search input
     */
    focusSearch() {
        if (this.searchInput) {
            this.searchInput.focus();
            this.searchInput.select();
        }
    }

    /**
     * Handle keyboard navigation
     * @param {KeyboardEvent} e - Keyboard event
     */
    handleKeyDown(e) {
        // Handle Enter key
        if (e.key === 'Enter') {
            const firstResult = this.resultsList?.querySelector('.search-result-item');
            if (firstResult) {
                firstResult.click();
            }
        }
        
        // Handle Escape key
        if (e.key === 'Escape') {
            this.hideResults();
            this.searchInput.blur();
        }
    }

    /**
     * Get current search mode
     * @returns {string} Current mode
     */
    getMode() {
        return this.mode;
    }

    /**
     * Check if search is initialized
     * @returns {boolean} Initialization status
     */
    isReady() {
        return this.isInitialized;
    }
    
    /**
     * Extract text snippet from document content with search term highlighted
     * @param {Object} doc - Document object
     * @param {string} searchTerm - Search term to highlight
     * @returns {string} HTML snippet with highlights
     */
    extractSnippet(doc, searchTerm) {
        if (!doc.text) return '';
        
        const text = doc.text;
        const lowerText = text.toLowerCase();
        const lowerTerm = searchTerm.toLowerCase();
        
        // Find the first occurrence of the search term
        let index = lowerText.indexOf(lowerTerm);
        if (index === -1) {
            // If exact term not found, try first word of search term
            const firstWord = lowerTerm.split(' ')[0];
            index = lowerText.indexOf(firstWord);
        }
        
        if (index === -1) {
            // Return first 200 characters if no match found
            return text.substring(0, 200) + (text.length > 200 ? '...' : '');
        }
        
        // Extract snippet around the match
        const snippetLength = 200;
        const start = Math.max(0, index - 50);
        const end = Math.min(text.length, start + snippetLength);
        
        let snippet = text.substring(start, end);
        
        // Add ellipsis if we're not at the beginning/end
        if (start > 0) snippet = '...' + snippet;
        if (end < text.length) snippet = snippet + '...';
        
        // Highlight the search term (case-insensitive)
        const regex = new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
        snippet = snippet.replace(regex, '<mark>$1</mark>');
        
        return snippet;
    }

    /**
     * Show QR code modal
     * @param {string} url - URL to generate QR code for
     */
    showQRCodeModal(url) {
        // Remove existing modal
        this.hideQRCodeModal();
        
        // Create modal using the same structure as the original
        const modal = document.createElement('div');
        modal.id = 'qr-code-modal';
        modal.className = 'modal qr-modal';
        modal.innerHTML = `
            <div class="modal-content qr-modal-content">
                <div class="modal-header">
                    <h2>QR Code</h2>
                    <button class="modal-close" id="close-qr-modal">&times;</button>
                </div>
                <div class="modal-body qr-modal-body">
                    <div class="qr-loading">
                        <div class="spinner"></div>
                        <p>Generating QR code...</p>
                    </div>
                    <img class="qr-code-image" alt="QR Code" style="display: none;">
                    <div class="qr-code-info">
                        <p>Scan this QR code to open:</p>
                        <a class="qr-code-url" href="${url}" target="_blank" rel="noopener">${url}</a>
                    </div>
                </div>
            </div>
        `;
        
        document.body.appendChild(modal);
        
        // Add event listeners
        const closeBtn = modal.querySelector('#close-qr-modal');
        closeBtn.addEventListener('click', () => this.hideQRCodeModal());
        
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                this.hideQRCodeModal();
            }
        });
        
        // Close on Escape key
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && modal.style.display !== 'none') {
                this.hideQRCodeModal();
            }
        });
        
        // Generate QR code
        this.generateQRCode(url, modal.querySelector('.qr-loading'));
    }
    
    /**
     * Hide QR code modal
     */
    hideQRCodeModal() {
        const existingModal = document.querySelector('#qr-code-modal');
        if (existingModal) {
            existingModal.remove();
        }
    }
    
    /**
     * Generate QR code for URL
     * @param {string} url - URL to encode
     * @param {HTMLElement} container - Container to place QR code
     */
    generateQRCode(url, container) {
        // Use the API QR route as in the original implementation
        const qrUrl = `/api/qr?text=${encodeURIComponent(url)}&size=256`;
        
        const img = document.createElement('img');
        img.src = qrUrl;
        img.alt = 'QR Code';
        img.className = 'qr-code-image';
        
        img.onload = () => {
            container.innerHTML = '';
            container.appendChild(img);
        };
        
        img.onerror = () => {
            container.innerHTML = '<div class="qr-error">Failed to generate QR code</div>';
        };
    }
}
