/**
 * MbetterClient Dashboard JavaScript - Offline-first functionality
 */

// Dashboard namespace
window.Dashboard = (function() {
    'use strict';

    let config = {};
    let statusInterval = null;
    let isOnline = navigator.onLine;
    let cache = {};
    let initialized = false; // Prevent multiple initializations
    
    // Initialize dashboard
    function init(userConfig) {
        if (initialized) {
            console.log('Dashboard already initialized, skipping...');
            return;
        }

        config = Object.assign({
            statusUpdateInterval: 5000,
            apiEndpoint: '/api',
            user: null
        }, userConfig);

        console.log('Dashboard initializing...', config);

        // Setup event listeners
        setupEventListeners();

        // Start status updates
        startStatusUpdates();

        // Setup offline/online detection
        setupOfflineDetection();

        // Load cached data
        loadFromCache();

        // Initialize match timer
        initMatchTimer();

        initialized = true;
        console.log('Dashboard initialized successfully');
    }
    
    // Setup event listeners
    function setupEventListeners() {
        // Generic API form handling
        document.addEventListener('submit', function(e) {
            if (e.target.classList.contains('api-form')) {
                e.preventDefault();
                handleApiForm(e.target);
            }
        });
        
        // Generic API button handling
        document.addEventListener('click', function(e) {
            if (e.target.classList.contains('api-btn')) {
                e.preventDefault();
                handleApiButton(e.target);
            }
        });
        
        // Toast notifications
        setupToastNotifications();
    }
    
    // Setup offline/online detection
    function setupOfflineDetection() {
        window.addEventListener('online', function() {
            isOnline = true;
            showNotification('Connection restored', 'success');
            updateOnlineStatus();
            // Sync cached changes when coming back online
            syncCachedChanges();
        });
        
        window.addEventListener('offline', function() {
            isOnline = false;
            showNotification('You are now offline', 'warning');
            updateOnlineStatus();
        });
        
        updateOnlineStatus();
    }
    
    // Update online status indicator
    function updateOnlineStatus() {
        const indicators = document.querySelectorAll('.online-status');
        indicators.forEach(function(indicator) {
            indicator.textContent = isOnline ? 'Online' : 'Offline';
            indicator.className = 'online-status badge ' + (isOnline ? 'bg-success' : 'bg-warning');
        });
    }
    
    // Start periodic status updates
    function startStatusUpdates() {
        if (statusInterval) {
            clearInterval(statusInterval);
        }
        
        // Initial update
        updateSystemStatus();
        
        // Periodic updates
        statusInterval = setInterval(function() {
            if (isOnline) {
                updateSystemStatus();
            }
        }, config.statusUpdateInterval);
    }
    
    // Update system status
    function updateSystemStatus() {
        apiRequest('GET', '/status')
        .then(function(data) {
            updateStatusDisplay(data);
            cacheData('system_status', data);
        })
        .catch(function(error) {
            console.error('Failed to update system status:', error);
            // Use cached data if available
            const cached = getFromCache('system_status');
            if (cached) {
                updateStatusDisplay(cached);
            }
        });
    }
    
    // Update status display elements
    function updateStatusDisplay(data) {
        // Update system status
        const systemStatus = document.getElementById('system-status');
        if (systemStatus && data.status) {
            systemStatus.textContent = data.status.charAt(0).toUpperCase() + data.status.slice(1);
            systemStatus.className = 'badge ' + (data.status === 'online' ? 'bg-success' : 'bg-danger');
        }
        
        // Update last updated time
        const lastUpdated = document.getElementById('last-updated');
        if (lastUpdated) {
            lastUpdated.textContent = new Date().toLocaleTimeString();
        }
        
        // Update component status
        if (data.components) {
            Object.keys(data.components).forEach(function(component) {
                const badge = document.getElementById(component + '-badge');
                if (badge) {
                    const status = data.components[component];
                    badge.className = 'badge me-1 ' + (status === 'running' ? 'bg-success' : 'bg-secondary');
                }
            });
        }
    }
    
    // Generic API request handler
    function apiRequest(method, endpoint, data) {
        const url = config.apiEndpoint + endpoint;
        const options = {
            method: method,
            headers: {
                'Content-Type': 'application/json',
            }
        };
        
        if (data) {
            options.body = JSON.stringify(data);
        }
        
        return fetch(url, options)
        .then(function(response) {
            if (!response.ok) {
                throw new Error('API request failed: ' + response.status);
            }
            return response.json();
        });
    }
    
    // Handle API form submissions
    function handleApiForm(form) {
        const formData = new FormData(form);
        const data = {};
        
        formData.forEach(function(value, key) {
            data[key] = value;
        });
        
        const method = form.dataset.method || 'POST';
        const endpoint = form.dataset.endpoint;
        
        if (!endpoint) {
            console.error('Form missing data-endpoint attribute');
            return;
        }
        
        showLoading(form);
        
        apiRequest(method, endpoint, data)
        .then(function(response) {
            hideLoading(form);
            
            if (response.success) {
                showNotification(response.message || 'Operation completed successfully', 'success');
                form.reset();
                
                // Refresh data if needed
                const refreshTarget = form.dataset.refresh;
                if (refreshTarget) {
                    refreshSection(refreshTarget);
                }
            } else {
                showNotification(response.error || 'Operation failed', 'error');
            }
        })
        .catch(function(error) {
            hideLoading(form);
            showNotification('Error: ' + error.message, 'error');
            
            // Cache the operation for later if offline
            if (!isOnline) {
                cacheOperation(method, endpoint, data);
                showNotification('Operation cached for when connection is restored', 'info');
            }
        });
    }
    
    // Handle API button clicks
    function handleApiButton(button) {
        const method = button.dataset.method || 'POST';
        const endpoint = button.dataset.endpoint;
        const data = JSON.parse(button.dataset.data || '{}');
        
        if (!endpoint) {
            console.error('Button missing data-endpoint attribute');
            return;
        }
        
        // Confirmation if requested
        if (button.dataset.confirm) {
            if (!confirm(button.dataset.confirm)) {
                return;
            }
        }
        
        showLoading(button);
        
        apiRequest(method, endpoint, data)
        .then(function(response) {
            hideLoading(button);
            
            if (response.success) {
                showNotification(response.message || 'Operation completed successfully', 'success');
                
                // Refresh data if needed
                const refreshTarget = button.dataset.refresh;
                if (refreshTarget) {
                    refreshSection(refreshTarget);
                }
            } else {
                showNotification(response.error || 'Operation failed', 'error');
            }
        })
        .catch(function(error) {
            hideLoading(button);
            showNotification('Error: ' + error.message, 'error');
            
            // Cache the operation for later if offline
            if (!isOnline) {
                cacheOperation(method, endpoint, data);
                showNotification('Operation cached for when connection is restored', 'info');
            }
        });
    }
    
    // Show loading state
    function showLoading(element) {
        element.classList.add('loading');
        element.disabled = true;
    }
    
    // Hide loading state
    function hideLoading(element) {
        element.classList.remove('loading');
        element.disabled = false;
    }
    
    // Refresh a section
    function refreshSection(sectionId) {
        const section = document.getElementById(sectionId);
        if (!section) return;
        
        // Add refresh logic here based on section type
        console.log('Refreshing section:', sectionId);
    }
    
    // Cache management
    function cacheData(key, data) {
        try {
            cache[key] = {
                data: data,
                timestamp: Date.now()
            };
            localStorage.setItem('dashboard_cache', JSON.stringify(cache));
        } catch (e) {
            console.warn('Failed to cache data:', e);
        }
    }
    
    function getFromCache(key) {
        try {
            const cached = cache[key];
            if (cached && (Date.now() - cached.timestamp) < 300000) { // 5 minutes
                return cached.data;
            }
        } catch (e) {
            console.warn('Failed to get cached data:', e);
        }
        return null;
    }
    
    function loadFromCache() {
        try {
            const cached = localStorage.getItem('dashboard_cache');
            if (cached) {
                cache = JSON.parse(cached);
            }
        } catch (e) {
            console.warn('Failed to load cache:', e);
            cache = {};
        }
    }
    
    // Cache operations for offline sync
    function cacheOperation(method, endpoint, data) {
        try {
            let operations = JSON.parse(localStorage.getItem('cached_operations') || '[]');
            operations.push({
                method: method,
                endpoint: endpoint,
                data: data,
                timestamp: Date.now()
            });
            localStorage.setItem('cached_operations', JSON.stringify(operations));
        } catch (e) {
            console.warn('Failed to cache operation:', e);
        }
    }
    
    // Sync cached operations when coming back online
    function syncCachedChanges() {
        try {
            const operations = JSON.parse(localStorage.getItem('cached_operations') || '[]');
            
            if (operations.length === 0) return;
            
            console.log('Syncing', operations.length, 'cached operations');
            
            operations.forEach(function(operation, index) {
                apiRequest(operation.method, operation.endpoint, operation.data)
                .then(function(response) {
                    console.log('Synced operation', index + 1, '/', operations.length);
                })
                .catch(function(error) {
                    console.error('Failed to sync operation:', error);
                });
            });
            
            // Clear cached operations
            localStorage.removeItem('cached_operations');
            showNotification('Cached changes synchronized', 'success');
            
        } catch (e) {
            console.warn('Failed to sync cached operations:', e);
        }
    }
    
    // Toast notifications
    function setupToastNotifications() {
        // Create toast container if it doesn't exist
        if (!document.getElementById('toast-container')) {
            const container = document.createElement('div');
            container.id = 'toast-container';
            container.className = 'toast-container position-fixed bottom-0 end-0 p-3';
            container.style.zIndex = '1060';
            document.body.appendChild(container);
        }
    }
    
    function showNotification(message, type) {
        const container = document.getElementById('toast-container');
        if (!container) return;
        
        const toastId = 'toast-' + Date.now();
        const iconClass = {
            'success': 'fas fa-check-circle text-success',
            'error': 'fas fa-exclamation-triangle text-danger',
            'warning': 'fas fa-exclamation-triangle text-warning',
            'info': 'fas fa-info-circle text-info'
        }[type] || 'fas fa-info-circle text-info';
        
        const toast = document.createElement('div');
        toast.id = toastId;
        toast.className = 'toast';
        toast.setAttribute('role', 'alert');
        toast.innerHTML = `
            <div class="toast-header">
                <i class="${iconClass} me-2"></i>
                <strong class="me-auto">MbetterClient</strong>
                <small class="text-muted">now</small>
                <button type="button" class="btn-close" data-bs-dismiss="toast"></button>
            </div>
            <div class="toast-body">
                ${message}
            </div>
        `;
        
        container.appendChild(toast);
        
        // Initialize and show toast
        if (typeof bootstrap !== 'undefined') {
            const bsToast = new bootstrap.Toast(toast, { delay: 5000 });
            bsToast.show();
            
            // Remove from DOM after hiding
            toast.addEventListener('hidden.bs.toast', function() {
                toast.remove();
            });
        } else {
            // Fallback without Bootstrap
            setTimeout(function() {
                toast.remove();
            }, 5000);
        }
    }
    
    // Video control helpers
    function updateVideoStatus() {
        apiRequest('GET', '/video/status')
        .then(function(data) {
            const statusElement = document.getElementById('video-status');
            if (statusElement && data.player_status) {
                statusElement.textContent = data.player_status.charAt(0).toUpperCase() + data.player_status.slice(1);
                statusElement.className = 'badge ' + (data.player_status === 'playing' ? 'bg-success' : 'bg-secondary');
            }
            cacheData('video_status', data);
        })
        .catch(function(error) {
            console.error('Failed to update video status:', error);
            const cached = getFromCache('video_status');
            if (cached && document.getElementById('video-status')) {
                document.getElementById('video-status').textContent = cached.player_status || 'Unknown';
            }
        });
    }

    // Server-side Match Timer functionality
    let matchTimerInterval = null;
    let serverTimerState = {
        running: false,
        remaining_seconds: 0,
        total_seconds: 0,
        fixture_id: null,
        match_id: null,
        start_time: null
    };
    let lastServerSync = 0;
    let cachedMatchInterval = null; // Cache the match interval configuration
    const SYNC_INTERVAL = 30000; // Sync with server every 30 seconds
    let longPollingActive = false; // Flag to control long polling
    let longPollingController = null; // AbortController for cancelling requests

    function initMatchTimer() {
        console.log('Initializing server-only match timer with real-time notifications...');

        // Load match interval config once at initialization
        loadMatchIntervalConfig().then(function(intervalSeconds) {
            console.log('Match timer config loaded at initialization:', intervalSeconds, 'seconds');

            // Initial sync with server
            syncWithServerTimer();

            // Start real-time notification polling for timer updates
            startNotificationPolling();

        }).catch(function(error) {
            console.error('Failed to load match timer config at initialization:', error);
            // Use default and continue
            cachedMatchInterval = 20 * 60; // Default 20 minutes

            // Initial sync with server
            syncWithServerTimer();

            // Start real-time notification polling for timer updates
            startNotificationPolling();
        });
    }

    function syncWithServerTimer() {
        const now = Date.now();

        apiRequest('GET', '/match-timer/state')
        .then(function(data) {
            if (data.success) {
                // Update server state
                serverTimerState = {
                    running: data.running || false,
                    remaining_seconds: data.remaining_seconds || 0,
                    total_seconds: data.total_seconds || 0,
                    fixture_id: data.fixture_id || null,
                    match_id: data.match_id || null,
                    start_time: data.start_time || null
                };

                lastServerSync = now;

                console.log('Synced with server timer:', serverTimerState);

                // Update display immediately
                updateMatchTimerDisplay();

                // No local countdown needed - server handles everything
                console.log('Server timer state updated, display refreshed');
            } else {
                console.error('Failed to sync with server timer:', data);
            }
        })
        .catch(function(error) {
            console.error('Failed to sync with server timer:', error);
            // Continue with local countdown if server is unavailable
        });
    }

    function loadMatchIntervalConfig() {
        // Only load config if we don't have it cached
        if (cachedMatchInterval !== null) {
            return Promise.resolve(cachedMatchInterval);
        }

        return apiRequest('GET', '/match-timer/config')
        .then(function(data) {
            if (data.success && data.match_interval) {
                cachedMatchInterval = data.match_interval * 60; // Convert minutes to seconds
                console.log('Loaded match interval config:', cachedMatchInterval, 'seconds');
                return cachedMatchInterval;
            } else {
                console.error('Failed to get match timer config:', data);
                // Fallback to 20 minutes
                cachedMatchInterval = 20 * 60;
                return cachedMatchInterval;
            }
        })
        .catch(function(error) {
            console.error('Failed to load match timer config:', error);
            // Fallback to 20 minutes
            cachedMatchInterval = 20 * 60;
            return cachedMatchInterval;
        });
    }

    function startLocalCountdown() {
        // DISABLE local countdown - rely only on server updates
        console.log('Local countdown disabled - using server-only updates');
        
        if (matchTimerInterval && matchTimerInterval !== 'sync') {
            clearInterval(matchTimerInterval);
        }
        
        // Only update display, no local counting
        updateMatchTimerDisplay();
    }

    function stopLocalCountdown() {
        if (matchTimerInterval && matchTimerInterval !== 'sync') {
            clearInterval(matchTimerInterval);
            matchTimerInterval = null;
        }
    }

    function stopNotificationPolling() {
        console.log('Stopping long polling for notifications...');
        longPollingActive = false;

        // Cancel any ongoing request
        if (longPollingController) {
            longPollingController.abort();
            longPollingController = null;
        }
    }

    function updateMatchTimerDisplay() {
        let displaySeconds = serverTimerState.remaining_seconds;

        // Update status text based on timer state
        const timerStatus = document.getElementById('timer-status');
        if (timerStatus) {
            if (serverTimerState.running) {
                timerStatus.textContent = 'Timer running';
                timerStatus.className = 'text-success';
            } else {
                timerStatus.textContent = 'Waiting for games to start...';
                timerStatus.className = 'text-muted';
            }
        }

        // If server timer is not running, show configured interval
        if (!serverTimerState.running) {
            // Use cached config if available, otherwise load it
            if (cachedMatchInterval !== null) {
                updateTimerElements(cachedMatchInterval);
            } else {
                // Only load config if not cached (should happen at initialization)
                // Don't load it here to avoid repeated API calls
                updateTimerElements(20 * 60); // Use default 20 minutes
            }
        } else {
            updateTimerElements(displaySeconds);
        }
    }

    function updateTimerElements(seconds) {
        const minutes = Math.floor(seconds / 60);
        const remainingSeconds = seconds % 60;
        const timeString = minutes.toString().padStart(2, '0') + ':' + remainingSeconds.toString().padStart(2, '0');

        // Update status bar timer
        const statusTimer = document.getElementById('match-timer');
        if (statusTimer) {
            statusTimer.textContent = timeString;

            // Change color based on time remaining
            if (seconds <= 60) { // Last minute
                statusTimer.className = 'badge bg-danger text-white';
            } else if (seconds <= 300) { // Last 5 minutes
                statusTimer.className = 'badge bg-warning text-dark';
            } else {
                statusTimer.className = 'badge bg-secondary text-white';
            }

            // Add pulse animation for last minute
            if (seconds <= 60) {
                statusTimer.style.animation = 'timerPulse 0.5s infinite';
            } else {
                statusTimer.style.animation = '';
            }
        }

        // Update navbar timer (for cashier dashboard)
        const navbarTimer = document.getElementById('match-timer-display');
        if (navbarTimer) {
            navbarTimer.textContent = timeString;
            navbarTimer.className = seconds <= 60 ? 'text-danger fw-bold' : 'text-warning fw-bold';
        }

        // Update admin dashboard timer if present
        const adminTimer = document.getElementById('admin-match-timer');
        if (adminTimer) {
            adminTimer.textContent = timeString;
            adminTimer.className = seconds <= 60 ? 'text-danger fw-bold' : 'text-warning fw-bold';
        }
    }

    function onServerTimerExpired() {
        console.log('Server timer expired, match should be starting...');

        // Show notification that match is starting
        showNotification('Match timer expired - starting next match...', 'info');

        // Reload match interval config when timer reaches 0 and needs reset
        loadMatchIntervalConfig().then(function(intervalSeconds) {
            console.log('Reloaded match interval config for reset:', intervalSeconds, 'seconds');

            // Reset timer with the (possibly updated) configuration
            serverTimerState.remaining_seconds = intervalSeconds;
            serverTimerState.total_seconds = intervalSeconds;

            // Sync with server to get updated state
            setTimeout(function() {
                syncWithServerTimer();
            }, 2000); // Wait 2 seconds for server to process
        });
    }

    function startNotificationPolling() {
        console.log('Starting long polling for real-time notifications...');

        if (longPollingActive) {
            stopNotificationPolling();
        }

        longPollingActive = true;
        performLongPoll();
    }

    function performLongPoll() {
        if (!longPollingActive || !isOnline) {
            return;
        }

        // Create AbortController for this request
        longPollingController = new AbortController();
        const signal = longPollingController.signal;

        // Make long polling request (server handles 30-second timeout)
        const url = config.apiEndpoint + '/notifications?_=' + Date.now() + Math.random();
        const options = {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
            },
            signal: signal
        };

        fetch(url, options)
        .then(function(response) {
            if (!response.ok) {
                throw new Error('HTTP ' + response.status);
            }
            return response.json();
        })
        .then(function(data) {
            if (data.success && data.notifications && data.notifications.length > 0) {
                // Process each notification
                data.notifications.forEach(function(notification) {
                    handleNotification(notification);
                });
            }

            // Immediately start the next long poll after processing notifications
            if (longPollingActive) {
                // Small delay to prevent overwhelming the server
                setTimeout(performLongPoll, 100);
            }
        })
        .catch(function(error) {
            if (error.name === 'AbortError') {
                // Request was cancelled, don't restart
                console.debug('Long poll cancelled');
                return;
            }

            console.debug('Long poll failed:', error.message);

            // Retry after a delay if still active
            if (longPollingActive) {
                setTimeout(performLongPoll, 2000); // Retry after 2 seconds on error
            }
        });
    }

    function handleNotification(notification) {
        console.log('Received notification:', notification.type, notification);

        if (notification.type === 'TIMER_UPDATE' && notification.data) {
            // Update timer state from server notification
            serverTimerState = {
                running: notification.data.running || false,
                remaining_seconds: notification.data.remaining_seconds || 0,
                total_seconds: notification.data.total_seconds || 0,
                fixture_id: notification.data.fixture_id || null,
                match_id: notification.data.match_id || null,
                start_time: notification.data.start_time || null
            };

            // Update display immediately
            updateMatchTimerDisplay();

            console.log('Timer updated from notification:', serverTimerState);
        }
        else if (notification.type === 'START_GAME') {
            console.log('Start game notification received');
            onStartGameMessage();
            showNotification('Games started - match timer is now running', 'success');
        }
        else if (notification.type === 'MATCH_START') {
            console.log('Match started:', notification.data);
            showNotification('New match has started!', 'info');
        }
        else if (notification.type === 'GAME_STATUS') {
            console.log('Game status update:', notification.data);
            // Update system status if provided
            if (notification.data.status) {
                const systemStatus = document.getElementById('system-status');
                if (systemStatus) {
                    systemStatus.textContent = notification.data.status.charAt(0).toUpperCase() + notification.data.status.slice(1);
                    systemStatus.className = 'badge ' + (notification.data.status === 'running' ? 'bg-success' : 'bg-secondary');
                }
            }
        }
        else if (notification.type === 'FIXTURE_STATUS_UPDATE') {
            console.log('Fixture status update:', notification.data);
            // Trigger page refresh if on fixtures page
            if (window.location.pathname.includes('/fixtures')) {
                // Refresh fixtures data if function exists
                if (typeof loadFixtures === 'function') {
                    loadFixtures();
                }
                if (typeof loadFixtureDetails === 'function') {
                    loadFixtureDetails();
                }
            }
        }
        else {
            console.log('Unknown notification type:', notification.type);
        }
    }

    function onStartGameMessage() {
        console.log('Received START_GAME message, initializing timer...');

        // Load config and start timer when games start
        loadMatchIntervalConfig().then(function(intervalSeconds) {
            console.log('Loaded config for game start:', intervalSeconds, 'seconds');

            // Set timer state for the first time
            serverTimerState.running = true;
            serverTimerState.remaining_seconds = intervalSeconds;
            serverTimerState.total_seconds = intervalSeconds;

            // Update display
            updateMatchTimerDisplay();

            showNotification('Games started - match timer is now running', 'success');
        });
    }


    // Legacy functions for backward compatibility
    function startMatchTimer() {
        startServerTimer();
    }

    function stopMatchTimer() {
        stopServerTimer();
    }

    function resetMatchTimer(seconds) {
        // This is now handled by the server
        syncWithServerTimer();
    }

    function startNextMatch() {
        // This is now handled by the server-side timer
        console.log('startNextMatch called - now handled by server-side timer');
    }
    
    // Utility functions
    function formatBytes(bytes, decimals) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const dm = decimals < 0 ? 0 : decimals;
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
    }
    
    function formatTimestamp(timestamp) {
        return new Date(timestamp).toLocaleString();
    }
    
    // Public API
    return {
        init: init,
        apiRequest: apiRequest,
        showNotification: showNotification,
        updateVideoStatus: updateVideoStatus,
        updateSystemStatus: updateSystemStatus,
        formatBytes: formatBytes,
        formatTimestamp: formatTimestamp,
        isOnline: function() { return isOnline; },
        getConfig: function() { return config; },
        // Match timer functions
        initMatchTimer: initMatchTimer,
        startMatchTimer: startMatchTimer,
        stopMatchTimer: stopMatchTimer,
        resetMatchTimer: resetMatchTimer,
        startNextMatch: startNextMatch,
        stopNotificationPolling: stopNotificationPolling
    };
})();

// Auto-initialize if config is available
document.addEventListener('DOMContentLoaded', function() {
    const configScript = document.getElementById('dashboard-config');
    if (configScript && typeof Dashboard !== 'undefined') {
        try {
            const config = JSON.parse(configScript.textContent);
            Dashboard.init(config);
        } catch (e) {
            console.error('Failed to parse dashboard config:', e);
        }
    }
});