/**
 * ============================================
 * FLOWBOT DCI - UNIFIED CRAWLER JS v7.0
 * ============================================
 * Frontend JavaScript for unified crawler
 * ============================================
 */

(function() {
    'use strict';

    // ===== State =====
    const state = {
        jobId: null,
        status: 'ready',
        mode: 'search',
        polling: null,
        pollingInterval: 2000,
        startTime: null,
        domainStats: {},
        chart: null,
    };

    // ===== DOM Elements =====
    const elements = {
        form: document.getElementById('crawlerForm'),
        startBtn: document.getElementById('startBtn'),
        pauseBtn: document.getElementById('pauseBtn'),
        stopBtn: document.getElementById('stopBtn'),
        modeInput: document.getElementById('crawlMode'),
        searchTerms: document.getElementById('searchTerms'),
        seedUrls: document.getElementById('seedUrls'),
        searchTermsGroup: document.getElementById('searchTermsGroup'),
        seedUrlsGroup: document.getElementById('seedUrlsGroup'),
        searchEnginesGroup: document.getElementById('searchEnginesGroup'),
        toggleAdvanced: document.getElementById('toggleAdvanced'),
        advancedOptions: document.getElementById('advancedOptions'),
        relevanceThreshold: document.getElementById('relevanceThreshold'),
        relevanceValue: document.getElementById('relevanceValue'),
        progressValue: document.getElementById('progressValue'),
        currentJobId: document.getElementById('currentJobId'),
        statusIndicator: document.getElementById('statusIndicator'),
        logContent: document.getElementById('logContent'),
        toastContainer: document.getElementById('toastContainer'),

        // Stats
        statProcessed: document.getElementById('statProcessed'),
        statImported: document.getElementById('statImported'),
        statIgnored: document.getElementById('statIgnored'),
        statErrors: document.getElementById('statErrors'),
        elapsedTime: document.getElementById('elapsedTime'),
        etaTime: document.getElementById('etaTime'),
        processingRate: document.getElementById('processingRate'),
        memoryUsage: document.getElementById('memoryUsage'),

        // Tables
        domainsTable: document.getElementById('domainsTable'),
    };

    // ===== Initialization =====
    function init() {
        setupEventListeners();
        setupModeSelector();
        setupChipGroup();
        setupChart();
        updateUI();
    }

    function setupEventListeners() {
        // Form submission
        elements.form.addEventListener('submit', handleFormSubmit);

        // Control buttons
        elements.pauseBtn.addEventListener('click', handlePause);
        elements.stopBtn.addEventListener('click', handleStop);

        // Toggle advanced options
        elements.toggleAdvanced.addEventListener('click', () => {
            const isOpen = elements.advancedOptions.style.display !== 'none';
            elements.advancedOptions.style.display = isOpen ? 'none' : 'block';
            elements.toggleAdvanced.classList.toggle('open', !isOpen);
        });

        // Relevance threshold slider
        elements.relevanceThreshold.addEventListener('input', (e) => {
            elements.relevanceValue.textContent = e.target.value;
        });

        // Log filter buttons
        document.querySelectorAll('.filter-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                filterLogs(btn.dataset.filter);
            });
        });

        // Keyboard shortcuts
        document.addEventListener('keydown', handleKeyboard);
    }

    function setupModeSelector() {
        document.querySelectorAll('.mode-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                document.querySelectorAll('.mode-btn').forEach(b => b.classList.remove('active'));
                btn.classList.add('active');

                const mode = btn.dataset.mode;
                state.mode = mode;
                elements.modeInput.value = mode;

                updateModeUI(mode);
            });
        });
    }

    function updateModeUI(mode) {
        const showSearch = ['search', 'hybrid', 'infinite'].includes(mode);
        const showSeeds = ['deep', 'sitemap', 'hybrid'].includes(mode);
        const showEngines = ['search', 'hybrid', 'infinite'].includes(mode);

        elements.searchTermsGroup.style.display = showSearch ? 'block' : 'none';
        elements.seedUrlsGroup.style.display = showSeeds ? 'block' : 'none';
        elements.searchEnginesGroup.style.display = showEngines ? 'block' : 'none';
    }

    function setupChipGroup() {
        document.querySelectorAll('.chip input').forEach(input => {
            input.addEventListener('change', () => {
                input.closest('.chip').classList.toggle('active', input.checked);
            });
        });
    }

    function setupChart() {
        const ctx = document.getElementById('domainsChart');
        if (!ctx) return;

        // Add gradient definition to SVG
        const svg = document.querySelector('.progress-ring');
        if (svg) {
            const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
            defs.innerHTML = `
                <linearGradient id="progressGradient" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" style="stop-color:#6366f1"/>
                    <stop offset="100%" style="stop-color:#8b5cf6"/>
                </linearGradient>
            `;
            svg.prepend(defs);
        }

        state.chart = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: [],
                datasets: [{
                    label: 'Success',
                    data: [],
                    backgroundColor: 'rgba(16, 185, 129, 0.6)',
                    borderColor: '#10b981',
                    borderWidth: 1,
                }, {
                    label: 'Failed',
                    data: [],
                    backgroundColor: 'rgba(239, 68, 68, 0.6)',
                    borderColor: '#ef4444',
                    borderWidth: 1,
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: {
                        display: true,
                        position: 'top',
                        labels: {
                            color: '#94a3b8',
                            boxWidth: 12,
                            padding: 10,
                        }
                    }
                },
                scales: {
                    x: {
                        stacked: true,
                        ticks: { color: '#64748b', maxRotation: 45 },
                        grid: { display: false }
                    },
                    y: {
                        stacked: true,
                        ticks: { color: '#64748b' },
                        grid: { color: 'rgba(255,255,255,0.05)' }
                    }
                }
            }
        });
    }

    // ===== Form Handling =====
    async function handleFormSubmit(e) {
        e.preventDefault();

        const formData = new FormData(elements.form);
        const data = Object.fromEntries(formData.entries());

        // Get selected engines as array
        data.engines = Array.from(document.querySelectorAll('input[name="engines[]"]:checked'))
            .map(cb => cb.value);

        // Validate input
        if (state.mode === 'search' && !data.search_terms?.trim()) {
            showToast('error', 'Validation Error', 'Please enter search terms');
            return;
        }

        if (['deep', 'sitemap'].includes(state.mode) && !data.seed_urls?.trim()) {
            showToast('error', 'Validation Error', 'Please enter seed URLs');
            return;
        }

        try {
            setStatus('starting');
            disableForm(true);

            const response = await fetch('/api/v1/crawler/unified/start', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(data)
            });

            const result = await response.json();

            if (result.success) {
                state.jobId = result.data.job_id;
                state.startTime = Date.now();
                elements.currentJobId.textContent = state.jobId.substring(0, 20) + '...';

                showToast('success', 'Crawl Started', `Job ID: ${state.jobId.substring(0, 15)}...`);
                addLog('info', `Crawl started in ${state.mode} mode`);

                startPolling();
                setStatus('running');
            } else {
                throw new Error(result.error?.message || 'Failed to start crawl');
            }
        } catch (error) {
            showToast('error', 'Error', error.message);
            addLog('error', `Failed to start: ${error.message}`);
            setStatus('error');
            disableForm(false);
        }
    }

    async function handlePause() {
        if (!state.jobId) return;

        try {
            const action = state.status === 'paused' ? 'resume' : 'pause';
            const response = await fetch(`/api/v1/crawler/unified/${action}/${state.jobId}`, {
                method: 'POST'
            });

            const result = await response.json();

            if (result.success) {
                const newStatus = action === 'pause' ? 'paused' : 'running';
                setStatus(newStatus);
                showToast('info', 'Status Changed', `Crawl ${action}d`);
                addLog('warning', `Crawl ${action}d`);

                elements.pauseBtn.innerHTML = newStatus === 'paused'
                    ? '<span class="btn-icon">▶</span> Resume'
                    : '<span class="btn-icon">⏸</span> Pause';
            }
        } catch (error) {
            showToast('error', 'Error', error.message);
        }
    }

    async function handleStop() {
        if (!state.jobId) return;

        if (!confirm('Are you sure you want to stop the crawl?')) return;

        try {
            const response = await fetch(`/api/v1/crawler/unified/stop/${state.jobId}`, {
                method: 'POST'
            });

            const result = await response.json();

            if (result.success) {
                stopPolling();
                setStatus('cancelled');
                showToast('warning', 'Crawl Stopped', 'The crawl has been cancelled');
                addLog('warning', 'Crawl stopped by user');
                disableForm(false);
            }
        } catch (error) {
            showToast('error', 'Error', error.message);
        }
    }

    // ===== Polling =====
    function startPolling() {
        if (state.polling) clearInterval(state.polling);

        state.polling = setInterval(fetchProgress, state.pollingInterval);
        fetchProgress(); // Immediate first fetch
    }

    function stopPolling() {
        if (state.polling) {
            clearInterval(state.polling);
            state.polling = null;
        }
    }

    async function fetchProgress() {
        if (!state.jobId) return;

        try {
            const response = await fetch(`/api/v1/crawler/unified/progress?id=${state.jobId}`);
            const result = await response.json();

            if (result.success) {
                updateProgress(result.data);

                // Check if completed
                if (['completed', 'failed', 'cancelled'].includes(result.data.status)) {
                    stopPolling();
                    setStatus(result.data.status);
                    disableForm(false);

                    if (result.data.status === 'completed') {
                        showToast('success', 'Crawl Completed',
                            `Imported ${result.data.imported} items`);
                    }
                }
            }
        } catch (error) {
            console.error('Progress fetch error:', error);
        }

        // Also fetch domain stats periodically
        fetchDomainStats();
    }

    async function fetchDomainStats() {
        try {
            const response = await fetch('/api/v1/crawler/unified/domains?per_page=10');
            const result = await response.json();

            if (result.success && result.data.domains) {
                updateDomainStats(result.data.domains);
            }
        } catch (error) {
            console.error('Domain stats fetch error:', error);
        }
    }

    // ===== UI Updates =====
    function updateProgress(data) {
        // Update stats
        elements.statProcessed.textContent = formatNumber(data.processed || 0);
        elements.statImported.textContent = formatNumber(data.imported || 0);
        elements.statIgnored.textContent = formatNumber(data.ignored || 0);
        elements.statErrors.textContent = formatNumber(data.errors || 0);

        // Update progress ring
        const progress = Math.min(100, data.progress || 0);
        elements.progressValue.textContent = Math.round(progress);
        updateProgressRing(progress);

        // Update time stats
        elements.elapsedTime.textContent = formatTime(data.elapsed_seconds || 0);
        elements.etaTime.textContent = data.remaining_seconds > 0
            ? formatTime(data.remaining_seconds)
            : '--:--:--';
        elements.processingRate.textContent = (data.processing_rate || 0).toFixed(1);
        elements.memoryUsage.textContent = (data.memory_usage_mb || 0).toFixed(1);
    }

    function updateProgressRing(percent) {
        const circle = document.querySelector('.progress-ring-fill');
        if (!circle) return;

        const radius = 54;
        const circumference = 2 * Math.PI * radius;
        const offset = circumference - (percent / 100) * circumference;

        circle.style.strokeDashoffset = offset;
    }

    function updateDomainStats(domains) {
        // Update chart
        if (state.chart) {
            state.chart.data.labels = domains.map(d => truncate(d.domain, 15));
            state.chart.data.datasets[0].data = domains.map(d => d.successful_visits);
            state.chart.data.datasets[1].data = domains.map(d => d.failed_visits);
            state.chart.update('none');
        }

        // Update table
        const tbody = elements.domainsTable.querySelector('tbody');
        tbody.innerHTML = domains.length === 0
            ? '<tr class="empty-row"><td colspan="4">No domain data yet</td></tr>'
            : domains.map(d => `
                <tr>
                    <td title="${d.domain}">${truncate(d.domain, 20)}</td>
                    <td>${d.total_visits}</td>
                    <td>${d.successful_visits}</td>
                    <td>${d.success_rate || 0}%</td>
                </tr>
            `).join('');
    }

    function setStatus(status) {
        state.status = status;

        const indicator = elements.statusIndicator;
        indicator.className = 'status-indicator ' + status;
        indicator.querySelector('.status-text').textContent = capitalize(status);

        // Update button states
        const isRunning = status === 'running';
        const isPaused = status === 'paused';
        const isActive = isRunning || isPaused;

        elements.startBtn.disabled = isActive;
        elements.pauseBtn.disabled = !isActive;
        elements.stopBtn.disabled = !isActive;
    }

    function disableForm(disabled) {
        const inputs = elements.form.querySelectorAll('input, textarea, select, button:not(#pauseBtn):not(#stopBtn)');
        inputs.forEach(input => input.disabled = disabled);
    }

    function updateUI() {
        updateModeUI(state.mode);
    }

    // ===== Logging =====
    function addLog(level, message) {
        const time = new Date().toLocaleTimeString('en-US', { hour12: false });

        const logLine = document.createElement('div');
        logLine.className = `log-line ${level}`;
        logLine.innerHTML = `
            <span class="log-time">[${time}]</span>
            <span class="log-msg">${escapeHtml(message)}</span>
        `;

        elements.logContent.appendChild(logLine);
        elements.logContent.scrollTop = elements.logContent.scrollHeight;

        // Limit log lines
        while (elements.logContent.children.length > 500) {
            elements.logContent.removeChild(elements.logContent.firstChild);
        }
    }

    function filterLogs(filter) {
        const lines = elements.logContent.querySelectorAll('.log-line');
        lines.forEach(line => {
            if (filter === 'all') {
                line.style.display = '';
            } else {
                line.style.display = line.classList.contains(filter) ? '' : 'none';
            }
        });
    }

    // ===== Toast Notifications =====
    function showToast(type, title, message) {
        const icons = {
            success: '✓',
            error: '✕',
            warning: '⚠',
            info: 'ℹ'
        };

        const toast = document.createElement('div');
        toast.className = `toast ${type}`;
        toast.innerHTML = `
            <span class="toast-icon">${icons[type]}</span>
            <div class="toast-content">
                <div class="toast-title">${escapeHtml(title)}</div>
                <div class="toast-message">${escapeHtml(message)}</div>
            </div>
            <button class="toast-close">&times;</button>
        `;

        toast.querySelector('.toast-close').addEventListener('click', () => {
            toast.remove();
        });

        elements.toastContainer.appendChild(toast);

        // Auto-dismiss after 5 seconds
        setTimeout(() => {
            if (toast.parentNode) {
                toast.style.animation = 'slideIn 0.3s ease reverse';
                setTimeout(() => toast.remove(), 300);
            }
        }, 5000);
    }

    // ===== Keyboard Shortcuts =====
    function handleKeyboard(e) {
        // Ctrl+Enter to start
        if (e.ctrlKey && e.key === 'Enter') {
            e.preventDefault();
            if (!elements.startBtn.disabled) {
                elements.form.dispatchEvent(new Event('submit'));
            }
        }

        // Escape to stop
        if (e.key === 'Escape' && state.status === 'running') {
            handleStop();
        }
    }

    // ===== Utilities =====
    function formatNumber(num) {
        if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
        if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
        return num.toString();
    }

    function formatTime(seconds) {
        const h = Math.floor(seconds / 3600);
        const m = Math.floor((seconds % 3600) / 60);
        const s = Math.floor(seconds % 60);
        return `${pad(h)}:${pad(m)}:${pad(s)}`;
    }

    function pad(n) {
        return n.toString().padStart(2, '0');
    }

    function capitalize(str) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    }

    function truncate(str, len) {
        return str.length > len ? str.substring(0, len) + '...' : str;
    }

    function escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    // ===== Initialize =====
    document.addEventListener('DOMContentLoaded', init);

    // ===== Public API =====
    window.UnifiedCrawler = {
        getState: () => state,
        addLog,
        showToast,
    };

})();
