/**
 * Smart Polling Service for Live Match Updates
 * Implements dynamic frequency polling based on match states and user activity
 */
class SmartPollingService {
    constructor(options = {}) {
        // Get configuration from config system if available
        const config = window.smartPollingConfig?.getConfig() || {};
        
        this.options = {
            // Polling intervals (in milliseconds)
            intervals: config.intervals || {
                liveMatches: 30000,        // 30 seconds when live matches present
                upcomingMatches: 150000,   // 2.5 minutes when matches starting within 2 hours
                noMatches: 600000,         // 10 minutes when no live/upcoming matches
                backgroundTab: 300000      // 5 minutes when tab is not active
            },
            // Date to poll for (default: today in user's local timezone)
            date: options.date || (() => {
                const now = new Date();
                const year = now.getFullYear();
                const month = String(now.getMonth() + 1).padStart(2, '0');
                const day = String(now.getDate()).padStart(2, '0');
                return `${year}-${month}-${day}`;
            })(),
            // Callback when updates are received
            onUpdate: options.onUpdate || null,
            // Callback when polling state changes
            onStateChange: options.onStateChange || null,
            // Enable debug logging
            debug: config.debug || options.debug || false,
            ...options
        };

        this.isActive = false;
        this.currentInterval = null;
        this.timeoutId = null;
        this.isTabVisible = true;
        this.lastUpdateTime = null;
        this.consecutiveErrors = 0;
        this.maxErrors = 5;
        this.currentPollingMode = 'noMatches';
        
        // Bind methods to maintain context
        this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
        this.poll = this.poll.bind(this);
        
        // Initialize visibility API
        this.initializeVisibilityAPI();
        
        // Listen for configuration changes
        this.listenForConfigChanges();
        
        this.log('Smart Polling Service initialized');
    }

    /**
     * Listen for configuration changes
     */
    listenForConfigChanges() {
        document.addEventListener('smartPollingConfigChanged', (e) => {
            const newConfig = e.detail;
            
            // Update intervals
            this.options.intervals = newConfig.intervals;
            this.options.debug = newConfig.debug;
            
            this.log('Configuration updated, adjusting polling frequency');
            this.adjustPollingFrequency();
        });
    }

    /**
     * Initialize the Page Visibility API for background tab detection
     */
    initializeVisibilityAPI() {
        // Handle different browser implementations of Page Visibility API
        if (typeof document.hidden !== "undefined") {
            this.visibilityChange = "visibilitychange";
            this.hidden = "hidden";
        } else if (typeof document.msHidden !== "undefined") {
            this.visibilityChange = "msvisibilitychange";
            this.hidden = "msHidden";
        } else if (typeof document.webkitHidden !== "undefined") {
            this.visibilityChange = "webkitvisibilitychange";
            this.hidden = "webkitHidden";
        }

        if (this.visibilityChange) {
            document.addEventListener(this.visibilityChange, this.handleVisibilityChange, false);
        }

        // Also listen for window focus/blur as backup
        window.addEventListener('focus', () => {
            this.isTabVisible = true;
            this.adjustPollingFrequency();
        });

        window.addEventListener('blur', () => {
            this.isTabVisible = false;
            this.adjustPollingFrequency();
        });
    }

    /**
     * Handle visibility change events
     */
    handleVisibilityChange() {
        this.isTabVisible = !document[this.hidden];
        this.log(`Tab visibility changed: ${this.isTabVisible ? 'visible' : 'hidden'}`);
        this.adjustPollingFrequency();
    }

    /**
     * Start the smart polling service
     */
    start() {
        if (this.isActive) {
            this.log('Polling already active');
            return;
        }

        this.isActive = true;
        this.consecutiveErrors = 0;
        this.log('Starting smart polling service');
        
        // Add a small delay for the initial poll to ensure DOM and fixtures are ready
        setTimeout(() => {
            if (this.isActive) {
                this.poll();
            }
        }, 500); // 500ms delay for initial poll
    }

    /**
     * Stop the smart polling service
     */
    stop() {
        if (!this.isActive) {
            return;
        }

        this.isActive = false;
        if (this.timeoutId) {
            clearTimeout(this.timeoutId);
            this.timeoutId = null;
        }
        
        this.log('Smart polling service stopped');
        this.notifyStateChange('stopped');
    }

    /**
     * Update the date being polled
     */
    updateDate(newDate) {
        this.options.date = newDate;
        this.log(`Updated polling date to: ${newDate}`);
        
        if (this.isActive) {
            // Clear current timeout and start fresh poll cycle
            if (this.timeoutId) {
                clearTimeout(this.timeoutId);
            }
            this.poll();
        }
    }

    /**
     * Main polling function
     */
    async poll() {
        if (!this.isActive) {
            return;
        }

        try {
            this.log(`Polling for updates (mode: ${this.currentPollingMode})`);
            
            // Build URL with league filtering if lazy loading is active
            let pollUrl = `/public/ajax/match-status.php?date=${this.options.date}`;
            if (window.lazyFixtures && window.lazyFixtures.initialized) {
                const loadedLeagues = window.lazyFixtures.getLoadedLeagues();
                if (loadedLeagues.length > 0) {
                    pollUrl += `&league_ids=${loadedLeagues.join(',')}`;
                }
            }
            
            // Fetch match status updates
            const response = await fetch(pollUrl, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Requested-With': 'XMLHttpRequest',
                    'X-AJAX-Token': window.ajaxToken || ''
                }
            });

            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }

            const data = await response.json();
            
            if (data.success) {
                this.consecutiveErrors = 0;
                this.lastUpdateTime = new Date();
                
                // Always use fixed 30 second interval
                const hasLiveMatches = data.summary?.has_live || false;
                
                // Always trigger onUpdate callback
                if (this.options.onUpdate) {
                    this.options.onUpdate(data);
                }
                
            } else {
                throw new Error(data.error || 'Unknown error occurred');
            }
            
        } catch (error) {
            this.consecutiveErrors++;
            this.log(`Polling error (${this.consecutiveErrors}/${this.maxErrors}): ${error.message}`);
            
            if (this.consecutiveErrors >= this.maxErrors) {
                this.log('Max errors reached, stopping polling');
                this.stop();
                return;
            }
        }

        // Schedule next poll
        this.scheduleNextPoll();
    }

    /**
     * Analyze match states to determine optimal polling frequency
     */
    analyzeMatchStates(matches) {
        if (!matches || matches.length === 0) {
            return 'noMatches';
        }

        const now = new Date();
        const twoHoursFromNow = new Date(now.getTime() + (2 * 60 * 60 * 1000));
        const tenMinutesAgo = new Date(now.getTime() - (10 * 60 * 1000)); // 10 minutes ago
        
        let hasLiveMatches = false;
        let hasUpcomingMatches = false;
        let hasRecentlyFinishedMatches = false;

        for (const match of matches) {
            const status = match.status_short;
            
            // Check for live matches
            if (['1H', '2H', 'HT', 'ET', 'BT', 'P', 'LIVE'].includes(status)) {
                hasLiveMatches = true;
                break; // Live matches take priority
            }
            
            // Check for recently finished matches (finished in last 10 minutes)
            if (['FT', 'AET', 'PEN'].includes(status) && match.datetime) {
                const matchTime = new Date(match.datetime);
                // Estimate finish time as 2 hours after kick-off (rough estimate)
                const estimatedFinishTime = new Date(matchTime.getTime() + (2 * 60 * 60 * 1000));
                if (estimatedFinishTime >= tenMinutesAgo) {
                    hasRecentlyFinishedMatches = true;
                }
            }
            
            // Check for upcoming matches within 2 hours
            if (status === 'NS' && match.datetime) {
                const matchTime = new Date(match.datetime);
                if (matchTime <= twoHoursFromNow && matchTime > now) {
                    hasUpcomingMatches = true;
                }
            }
        }

        if (hasLiveMatches) {
            return 'liveMatches';
        } else if (hasRecentlyFinishedMatches) {
            // Keep polling recently finished matches at live frequency for a few minutes
            return 'liveMatches';
        } else if (hasUpcomingMatches) {
            return 'upcomingMatches';
        } else {
            return 'noMatches';
        }
    }

    /**
     * Update the current polling mode and frequency
     */
    updatePollingMode(newMode) {
        if (this.currentPollingMode !== newMode) {
            this.log(`Polling mode changed: ${this.currentPollingMode} -> ${newMode}`);
            this.currentPollingMode = newMode;
            this.notifyStateChange(newMode);
        }
        
        this.adjustPollingFrequency();
    }

    /**
     * Adjust polling frequency - always use 30 seconds
     */
    adjustPollingFrequency() {
        // Always use 30 second interval, regardless of match states or tab visibility
        const interval = 30000; // 30 seconds
        
        if (this.currentInterval !== interval) {
            this.currentInterval = interval;
        }
    }

    /**
     * Schedule the next poll
     */
    scheduleNextPoll() {
        if (!this.isActive) {
            return;
        }

        this.adjustPollingFrequency();
        
        this.timeoutId = setTimeout(() => {
            this.poll();
        }, this.currentInterval);
    }

    /**
     * Notify about state changes
     */
    notifyStateChange(state) {
        if (this.options.onStateChange) {
            this.options.onStateChange({
                state,
                interval: this.currentInterval,
                mode: this.currentPollingMode,
                isTabVisible: this.isTabVisible,
                lastUpdate: this.lastUpdateTime
            });
        }
    }

    /**
     * Get current polling status
     */
    getStatus() {
        return {
            isActive: this.isActive,
            currentMode: this.currentPollingMode,
            currentInterval: this.currentInterval,
            isTabVisible: this.isTabVisible,
            lastUpdateTime: this.lastUpdateTime,
            consecutiveErrors: this.consecutiveErrors,
            date: this.options.date
        };
    }

    /**
     * Log debug messages
     */
    log(message) {
        if (this.options.debug) {
            console.log(`[SmartPolling] ${message}`);
        }
    }

    /**
     * Clean up event listeners
     */
    destroy() {
        this.stop();
        
        if (this.visibilityChange) {
            document.removeEventListener(this.visibilityChange, this.handleVisibilityChange);
        }
        
        window.removeEventListener('focus', this.handleVisibilityChange);
        window.removeEventListener('blur', this.handleVisibilityChange);
        
        this.log('Smart Polling Service destroyed');
    }
}

// Make the class globally available
window.SmartPollingService = SmartPollingService;