// API Handler Template for Games
// --------------------------------
// HOW TO USE:
// 1. Copy this file to your new game project
// 2. Replace "GAME_NAME" with your actual game name (e.g., "zombiearrow", "woodtreasurehunt")
// 3. Include this file in your HTML before your main game script
// 4. Call apiHandler.generateToken() at game start
// 5. Call apiHandler.submitScoreIfNeeded(score) at game end

class APIHandler {
    constructor(baseUrl = 'https://cgames.unlimitedgames.info/realliferace') {
        this.baseUrl = baseUrl; // Base URL without /api.php
        this.session_id = Date.now().toString();
        this.cachedToken = localStorage.getItem('gameToken');
        this.cachedDeviceInfo = localStorage.getItem('deviceInfo') ? JSON.parse(localStorage.getItem('deviceInfo')) : null;
        this.scoreSubmitted = false; // Flag to track if score has been submitted
        this.gameStartTime = Date.now(); // When the game session started - initialize immediately
        this.lastActivityTime = Date.now(); // Initialize with current time
        this.lastScoreSubmissionTime = 0; // Track when the last score was submitted
        this.lastSubmittedScore = 0; // Track the last score value that was submitted
        this.gameToken = null; // Will store the verified token
        
        // Start tracking activity immediately
        this.setupGlobalActivityTracking();
        
        console.log('API Handler initialized with session_id:', this.session_id);
        console.log('Using base URL:', this.baseUrl);
    }
    
    // Verify token at game start
    async verifyTokenAtStart() {
        try {
            this.gameToken = await this.generateToken();
            console.log('Token verified at game start:', this.gameToken ? this.gameToken.substring(0, 10) + '...' : 'null');
            return this.gameToken;
        } catch (error) {
            console.error('Failed to verify token at game start:', error);
            
            // Create an emergency token even if verification fails
            console.log('Generating emergency token due to verification failure');
            this.gameToken = 'emergency_token_' + Date.now();
            return this.gameToken;
        }
    }

    // Set up global activity tracking - called on initialization
    setupGlobalActivityTracking() {
        // Set up global inactivity checker if not already done
        if (!window.inactivityChecker) {
            window.inactivityChecker = setInterval(() => {
                // Check if game has been inactive for too long
                if (this.isInactive()) {
                    this.handleInactivity();
                    
                    // Submit score on inactivity
                    this.submitScoreIfNeeded();
                }
            }, 10000); // Check every 10 seconds
        }
        
        // Set up global activity event listeners
        if (!window.activityTrackingInitialized) {
            // Track common user interactions
            document.addEventListener('click', () => this.updateActivity());
            document.addEventListener('keydown', () => this.updateActivity());
            document.addEventListener('touchstart', () => this.updateActivity());
            document.addEventListener('mousemove', () => this.updateActivity());
            
            // Add visibility change listener for tab switching
            document.addEventListener('visibilitychange', () => {
                if (document.visibilityState === 'hidden') {
                    console.log('Tab visibility changed - submitting score');
                    this.submitScoreIfNeeded();
                }
            });
            
            // Mark tracking as initialized to prevent duplicates
            window.activityTrackingInitialized = true;
        }
    }
    
    // Handle inactivity - directly shows message and terminates session
    handleInactivity() {
        // Don't handle multiple times
        if (document.getElementById('inactivity-overlay')) {
            return;
        }
        
        console.log("INACTIVE DETECTED! Showing message.");
        
        // Show inactivity message
        this.showInactivityMessage();
        
        // Dispatch event for game scripts
        const event = new CustomEvent('game:inactivity');
        document.dispatchEvent(event);
        
        // Clear the interval to prevent further checks
        if (window.inactivityChecker) {
            clearInterval(window.inactivityChecker);
            window.inactivityChecker = null;
        }
    }
    
    // Submit score if needed based on conditions
    async submitScoreIfNeeded(currentScore = window.playerData?.score || 0) {
        try {
            // Get current time
            const now = Date.now();
            const timeSinceLastSubmit = now - this.lastScoreSubmissionTime;
            
            // Check if we should submit the score:
            // 1. If it's been 10+ minutes since the last submission
            // 2. Or if the score has changed from the last submitted score
            if (timeSinceLastSubmit >= 10 * 60 * 1000 || currentScore !== this.lastSubmittedScore) {
                console.log('Submitting score due to:', 
                    timeSinceLastSubmit >= 10 * 60 * 1000 ? '10-minute interval' : 'score change',
                    'Current score:', currentScore);
                
                // Store the current score and time
                this.lastSubmittedScore = currentScore;
                this.lastScoreSubmissionTime = now;
                
                // Ensure we have a valid token
                if (!this.gameToken) {
                    console.log('No token found, generating new one before submitting score');
                    this.gameToken = await this.generateToken();
                }
                
                // Submit the score with whatever token we have (might be a development token)
                await this.submitFinalScore(this.gameToken, currentScore, 
                    Math.floor((now - this.gameStartTime) / 1000));
                return true;
            } else {
                // No need to submit yet
                return false;
            }
        } catch (error) {
            console.error('Error in submitScoreIfNeeded:', error);
            return false;
        }
    }
    
    // Show inactivity message when timeout is reached
    showInactivityMessage() {
        // Check if overlay already exists
        if (document.getElementById('inactivity-overlay')) {
            return;
        }
        
        // First try to stop the game
        this.pauseGame();
        
        // Create overlay
        const overlay = document.createElement('div');
        overlay.id = 'inactivity-overlay';
        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100%';
        overlay.style.height = '100%';
        overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.9)'; // Make more opaque
        overlay.style.color = 'white';
        overlay.style.display = 'flex';
        overlay.style.flexDirection = 'column';
        overlay.style.justifyContent = 'center';
        overlay.style.alignItems = 'center';
        overlay.style.zIndex = '99999'; // Extremely high z-index
        overlay.style.fontFamily = 'Arial, sans-serif';
        
        const message = document.createElement('h2');
        message.textContent = "You've been inactive. Click refresh to continue.";
        message.style.marginBottom = '20px';
        
        const subMessage = document.createElement('p');
        subMessage.textContent = 'Please refresh the page to start a new game';
        subMessage.style.marginBottom = '30px';
        
        const button = document.createElement('button');
        button.textContent = 'Refresh Page';
        button.style.padding = '10px 20px';
        button.style.fontSize = '16px';
        button.style.cursor = 'pointer';
        button.style.backgroundColor = '#4CAF50';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.onclick = () => {
            window.location.reload();
        };
        
        overlay.appendChild(message);
        overlay.appendChild(subMessage);
        overlay.appendChild(button);
        document.body.appendChild(overlay);
        
        // Create a full-page blocking div behind the overlay
        const blocker = document.createElement('div');
        blocker.id = 'game-blocker';
        blocker.style.position = 'fixed';
        blocker.style.top = '0';
        blocker.style.left = '0';
        blocker.style.width = '100%';
        blocker.style.height = '100%';
        blocker.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        blocker.style.zIndex = '99998'; // Just below the overlay
        document.body.appendChild(blocker);
        
        // Override animation frame to stop game
        if (window.requestAnimationFrame) {
            const oldRequestAnimationFrame = window.requestAnimationFrame;
            window.requestAnimationFrame = function() {
                // Do nothing, effectively pausing all animations
                return 0;
            };
            
            // Store the original for restoring later if needed
            window.origRequestAnimationFrame = oldRequestAnimationFrame;
        }
    }
    
    // Attempt to pause the game using various methods
    pauseGame() {
        try {
            // Method 1: Try to call the game's pause function if it exists
            if (window.pauseGame && typeof window.pauseGame === 'function') {
                console.log('Pausing game via global pauseGame function');
                window.pauseGame();
            }
            
            // Method 2: If using CreateJS, try to stop the Ticker
            if (window.createjs && window.createjs.Ticker) {
                console.log('Pausing game via CreateJS Ticker');
                window.createjs.Ticker.paused = true;
            }
            
            // Method 3: Try to access a common game variable if it exists
            if (window.game && typeof window.game.pause === 'function') {
                console.log('Pausing game via game.pause method');
                window.game.pause();
            }
            
            // Method 4: If using Phaser, try to pause
            if (window.Phaser && window.game instanceof Phaser.Game) {
                console.log('Pausing Phaser game');
                window.game.paused = true;
            }
            
            // Method 5: If using Three.js, try to stop animation
            if (window.THREE && window.renderer && window.animationId) {
                console.log('Cancelling Three.js animation frame');
                cancelAnimationFrame(window.animationId);
            }
            
            console.log('Game paused via multiple methods');
        } catch (error) {
            console.error('Error pausing game:', error);
        }
    }

    // Get device info, using cache if available
    _getDeviceInfo() {
        // Use cached device info if available to avoid recalculating
        if (this.cachedDeviceInfo) {
            return this.cachedDeviceInfo;
        }
        
        const userAgent = navigator.userAgent.toLowerCase();
        
        let device_type = 'unknown';
        let handset_os = 'unknown';
        let device_brand = 'unknown';
        let device_model = 'unknown';
        let country = 'US';
        let operator = 'unknown';
        
        // Try to detect OS
        if (userAgent.indexOf('android') > -1) {
            handset_os = 'android';
        } else if (
            userAgent.indexOf('iphone') > -1 || 
            userAgent.indexOf('ipad') > -1 || 
            userAgent.indexOf('ipod') > -1 || 
            (userAgent.indexOf('mac') > -1 && 'ontouchend' in document)
        ) {
            handset_os = 'ios';
        } else if (userAgent.indexOf('windows') > -1) {
            handset_os = 'windows';
        } else if (userAgent.indexOf('mac') > -1) {
            handset_os = 'macos';
        } else if (userAgent.indexOf('linux') > -1) {
            handset_os = 'linux';
        }
        
        // Try to detect device type
        if (userAgent.includes('mobile')) {
            device_type = 'mobile';
        } else if (userAgent.includes('tablet')) {
            device_type = 'tablet';
        } else {
            device_type = 'desktop';
        }
        
        // Try to detect brand and model
        if (handset_os === 'android') {
            if (userAgent.includes('samsung')) {
                device_brand = 'samsung';
                const modelMatch = userAgent.match(/sm-[a-z0-9]+/i) || userAgent.match(/gt-[a-z0-9]+/i);
                device_model = modelMatch ? modelMatch[0].toUpperCase() : 'Galaxy';
            } else if (userAgent.includes('huawei') || userAgent.includes('honor')) {
                device_brand = 'huawei';
                const modelMatch = userAgent.match(/(huawei|honor)[- ]([\w-]+)/i);
                device_model = modelMatch ? modelMatch[2].toUpperCase() : 'Unknown Model';
            } else if (userAgent.includes('xiaomi') || userAgent.includes('redmi') || userAgent.includes('mi')) {
                device_brand = 'xiaomi';
                const modelMatch = userAgent.match(/(redmi|mi)[- ]([\w-]+)/i);
                device_model = modelMatch ? modelMatch[2].toUpperCase() : 'Unknown Model';
            }
        } else if (handset_os === 'ios') {
            device_brand = 'apple';
            if (userAgent.includes('iphone')) {
                device_model = 'iPhone';
            } else if (userAgent.includes('ipad')) {
                device_model = 'iPad';
            } else if (userAgent.includes('ipod')) {
                device_model = 'iPod';
            }
        }
        
        // Detect country from browser language
        if (navigator.language) {
            const langParts = navigator.language.split('-');
            if (langParts.length > 1) {
                country = langParts[1].toUpperCase();
            }
        }
        
        // Set operator based on device brand
        operator = device_brand !== 'unknown' ? device_brand : 'chrome';
        
        const deviceInfo = { 
            handset_os,
            device_brand,
            device_model,
            device_type,
            country,
            operator
        };
        
        // Cache for future use
        this.cachedDeviceInfo = deviceInfo;
        localStorage.setItem('deviceInfo', JSON.stringify(deviceInfo));
        
        return deviceInfo;
    }

    // Generate a token for the game session
    async generateToken() {
        try {
            // Step 1: Check cached token
            if (this.cachedToken) {
                console.log('🔵 Found cached token, verifying...');

                // Always validate the token
                const isValid = await this.validateToken(this.cachedToken);
                if (isValid) {
                    console.log('✅ Cached token is valid. Using it.');
                    this.gameToken = this.cachedToken;
                    return this.cachedToken;
                } else {
                    console.warn('❌ Cached token is invalid. Generating new token.');
                    localStorage.removeItem('gameToken');
                }
            }

            // Step 2: Generate new token
            const deviceInfo = this._getDeviceInfo();
            const msisdn = '9800000000';
            const country = deviceInfo.country || 'US';
            const operator = deviceInfo.operator || 'chrome';

            console.log('🔵 Generating new token with device info:', deviceInfo);
            
            const url = `${this.baseUrl}/api.php/protoken?msisdn=${encodeURIComponent(msisdn)}&_country=${encodeURIComponent(country)}&_operator=${encodeURIComponent(operator)}`;
            console.log('🔵 Token URL:', url);

            try {
                const response = await fetch(url, {
                    method: 'GET',
                    headers: { 'Accept': 'text/plain' },
                    cache: 'no-cache',
                    mode: 'cors'
                });
                
                if (!response.ok) {
                    throw new Error(`Token request failed with status: ${response.status}`);
                }

                const token = (await response.text()).trim();
                if (!token) throw new Error('Token response is empty');

                localStorage.setItem('gameToken', token);
                this.cachedToken = token;
                this.gameToken = token;
                console.log('✅ New token received and saved:', token.substring(0, 10) + '...');
                
                // Set game start time when a new token is generated/validated
                this.gameStartTime = Date.now();
                this.lastActivityTime = Date.now();
                
                return token;
            } catch (fetchError) {
                console.error('❌ API error during token generation:', fetchError.message);
                // Create a fallback development token if API fails
                const fallbackToken = 'dev_token_' + Date.now() + '_' + Math.random().toString(36).substring(2, 15);
                this.gameToken = fallbackToken;
                this.cachedToken = fallbackToken;
                localStorage.setItem('gameToken', fallbackToken);
                console.log('⚠️ Using fallback token:', fallbackToken.substring(0, 10) + '...');
                return fallbackToken;
            }
        } catch (error) {
            console.error('❌ Error in generateToken:', error);
            
            // Emergency token as last resort
            const emergencyToken = 'emergency_token_' + Date.now();
            this.gameToken = emergencyToken;
            this.cachedToken = emergencyToken;
            localStorage.setItem('gameToken', emergencyToken);
            console.log('⚠️ Using emergency token:', emergencyToken.substring(0, 10) + '...');
            return emergencyToken;
        }
    }

    // Validate token with server
    async validateToken(token) {
        try {
            if (!token) {
                console.warn('⚠️ No token provided for validation');
                return false;
            }
            
            console.log('🔵 Validating token:', token.substring(0, 10) + '...');
            const validateUrl = `${this.baseUrl}/api.php/chktoken`; 
            
            const validationResponse = await fetch(validateUrl, {
                method: 'GET',
                headers: {
                    'Authorization': `Bearer ${token}`
                }
            });

            const validationText = await validationResponse.text();
            const isValid = validationText.trim().toLowerCase() === 'valid';
            
            if (isValid) {
                console.log('✅ Token validation successful');
            } else {
                console.warn('⚠️ Token validation failed');
            }
            
            return isValid;
        } catch (error) {
            console.error('❌ Token validation error:', error);
            return false;
        }
    }

    // Simple token check without async verification
    isTokenValid(token) {
        return token && token.length > 0;
    }
    
    // Update the last activity timestamp
    updateActivity() {
        this.lastActivityTime = Date.now();
    }
    
    // Check if the session is inactive
    isInactive(timeoutMs = 60 * 1000) { // 1 minute inactivity timeout
        if (!this.lastActivityTime) return false;
        return (Date.now() - this.lastActivityTime) > timeoutMs;
    }

    // Submit final score for the game
    async submitFinalScore(token, currentScore, totalDuration) {
        try {
            // Prevent multiple score submissions with the same token
            if (this.scoreSubmitted) {
                console.warn('⚠️ Score has already been submitted for this session');
                return { status: 'skipped', message: 'Score already submitted for this session' };
            }
            
            if (!token || totalDuration === undefined) {
                console.error('❌ Missing required score submission parameters');
                throw new Error('Missing required score submission parameters');
            }

            // 🚫 ABUSE CHECK: duration limits
            if (totalDuration < 5) {
                console.warn('⚠️ Suspicious: Game finished too quickly');
                throw new Error('Suspicious: Game finished too quickly');
            }
            if (totalDuration > 3600) {
                console.warn('⚠️ Suspicious: Game duration too long');
                throw new Error('Suspicious: Game duration too long');
            }

            // ✅ Continue only if checks passed
            console.log('🔵 SUBMIT SCORE: Starting submission for score:', currentScore);
            const deviceInfo = this._getDeviceInfo();
            const { handset_os, device_brand, device_model } = deviceInfo;
            console.log('🔵 SUBMIT SCORE: Device info:', { handset_os, device_brand, device_model });
            
            const gameStartTime = this.gameStartTime || (Date.now() - totalDuration * 1000);
            const gameEndTime = Date.now();

            // Format dates for API in the required format
            const formatDate = (date) => {
                const d = new Date(date);
                const local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);
                return `${local.getFullYear()}-${String(local.getMonth() + 1).padStart(2, '0')}-${String(local.getDate()).padStart(2, '0')}+${String(local.getHours()).padStart(2, '0')}:${String(local.getMinutes()).padStart(2, '0')}:${String(local.getSeconds()).padStart(2, '0')}`;
            };

            // Build API request parameters
            const params = [
                `handset_os=${encodeURIComponent(handset_os)}`,
                `device_brand=${encodeURIComponent(device_brand)}`,
                `device_model=${encodeURIComponent(device_model)}`,
                `gamename=realliferace`, // IMPORTANT: Replace with actual game name
                `gscore=${currentScore}`, // Use gscore parameter as expected by API
                `gduration=${totalDuration}`, // Use gduration as expected by API
                `session_id=${this.session_id}`,
                `gamestarttime=${formatDate(gameStartTime)}`,
                `gameendtime=${formatDate(gameEndTime)}`
            ];

            const url = `${this.baseUrl}/api.php/scorepost?${params.join('&')}`;
            console.log('🔵 SUBMIT SCORE: Submitting to URL:', url);

            try {
                const response = await fetch(url, {
                    method: 'GET',
                    headers: {
                        'Authorization': `Bearer ${token}`,
                        'Content-Type': 'application/json'
                    },
                    cache: 'no-cache'
                });

                console.log('🔵 SUBMIT SCORE: Response status:', response.status);
                
                if (!response.ok) {
                    const errorText = await response.text();
                    console.error('❌ SUBMIT SCORE: Submission failed with response:', errorText);
                    throw new Error(`Score submission failed: ${errorText}`);
                }

                // Mark score as submitted
                this.scoreSubmitted = true;
                console.log('✅ SUBMIT SCORE: Score successfully submitted!');
                
                try {
                    const data = await response.json();
                    console.log('✅ SUBMIT SCORE: Server response:', data);
                    return data;
                } catch (parseError) {
                    const textResponse = await response.text();
                    console.log('✅ SUBMIT SCORE: Server text response:', textResponse);
                    return { status: 'success', message: textResponse };
                }
            } catch (fetchError) {
                console.warn('⚠️ API error during score submission:', fetchError.message);
                
                // For development: Create a success response if API fails
                console.log('✅ FALLBACK: Recording score locally');
                
                // Still mark as submitted for tracking purposes
                this.scoreSubmitted = true;
                
                // Return mock response
                return { 
                    status: 'success', 
                    message: 'Development mode: Score recorded locally', 
                    score: currentScore,
                    timestamp: new Date().toISOString()
                };
            }
        } catch (error) {
            console.error('❌ SUBMIT SCORE: Error in score submission:', error);
            return { status: 'error', message: error.message };
        }
    }

    // Legacy method maintained for compatibility
    async submitScore(score) {
        console.log('submitScore called with score:', score);
        return this.submitScoreIfNeeded(score);
    }
}

// ✅ Use updated base URL (without /api.php) - REPLACE "GAME_NAME" with your game's name
const API_BASE_URL = 'https://cgames.unlimitedgames.info/realliferace';

// Create apiHandler immediately when the script is loaded
window.apiHandler = new APIHandler(API_BASE_URL);

// Ensure inactivity tracking is active from the moment the page loads
document.addEventListener('DOMContentLoaded', () => {
    console.log("Page loaded - activity tracking initialized");
    if (window.apiHandler) {
        window.apiHandler.updateActivity();
    }
});

document.addEventListener('game:tabchange', (event) => {
    // This can be used to handle tab changes in the game scripts
    console.log('Tab change detected:', event.detail?.message || 'No details');
    // Attempt to submit score if a game is in progress
    if (window.apiHandler) {
        window.apiHandler.submitScoreIfNeeded();
    }
});

document.addEventListener('game:unload', (event) => {
    // This can be used to handle page unload in the game scripts
    console.log('Page unload detected:', event.detail?.message || 'No details');
    // Attempt to submit score if a game is in progress
    if (window.apiHandler) {
        window.apiHandler.submitScoreIfNeeded();
    }
});

/* 
INTEGRATION GUIDE:

1. In your HTML file, include this script before your main game script:
   <script src="apiHandler.js"></script>
   <script src="your-game-script.js"></script>

2. In your game initialization code, generate a token:
   if(window.apiHandler && typeof window.apiHandler.generateToken === 'function') {
     window.apiHandler.generateToken();
   }

3. In your game end function, submit the score:
   if(window.apiHandler && typeof window.apiHandler.submitScoreIfNeeded === 'function') {
     window.apiHandler.submitScoreIfNeeded(yourGameScore);
   }

4. Make sure your game exposes the score in a playerData object:
   window.playerData = { 
     score: 0,
     // other game data
   };

5. Update the score in both your game and playerData:
   function updateScore(newScore) {
     // Update your game's internal score
     yourGameScore = newScore;
     
     // Update the playerData object for the API handler
     if (window.playerData) {
       window.playerData.score = newScore;
     }
   }
*/
