/**
 * Galaxy Strike Online - Logging System
 * Provides file-based logging with rotation and formatting
 * Renderer process version that uses IPC to communicate with main process
 */

class Logger {
    constructor() {
        this.logLevel = 'INFO';
        this.isRenderer = typeof window !== 'undefined' && typeof window.electronAPI !== 'undefined';
        this.timers = new Map();
        
        this.levels = {
            ERROR: 0,
            WARN: 1,
            INFO: 2,
            DEBUG: 3
        };
    }
    
    async initialize(appDataPath) {
        if (this.isRenderer) {
            // In renderer process, just log that we're ready
            console.log('Logger initialized in renderer process');
            return;
        }
        
        // Main process initialization (original code)
        const fs = require('fs').promises;
        const path = require('path');
        
        try {
            // Set up log directory in app storage location
            this.logDir = path.join(appDataPath, 'logs');
            
            // Create logs directory if it doesn't exist
            await fs.mkdir(this.logDir, { recursive: true });
            
            // Set current log file with full timestamp (YYYY-MM-DD-HH-MM-SS)
            const now = new Date();
            const timestamp = now.toISOString()
                .replace(/T/, '-')
                .replace(/\..+/, '')
                .replace(/:/g, '-');
            this.currentLogFile = path.join(this.logDir, `galaxy-strike-${timestamp}.log`);
            
            // Test write to ensure permissions
            await this.writeToFile('=== Galaxy Strike Online Log Session Started ===\n');
            
            this.isInitialized = true;
            console.log(`Logger initialized: ${this.logDir}`);
            
        } catch (error) {
            console.error('Failed to initialize logger:', error);
            this.isInitialized = false;
        }
    }
    
    async writeToFile(message) {
        if (this.isRenderer) {
            // In renderer process, send to main process via IPC
            return;
        }
        
        if (!this.isInitialized || !this.currentLogFile) return;
        
        try {
            const fs = require('fs').promises;
            
            // Check if file needs rotation
            await this.rotateLogIfNeeded();
            
            // Append message to current log file
            await fs.appendFile(this.currentLogFile, message, 'utf8');
        } catch (error) {
            console.error('Failed to write to log file:', error);
        }
    }
    
    async rotateLogIfNeeded() {
        if (this.isRenderer) return;
        
        const fs = require('fs').promises;
        const path = require('path');
        
        try {
            const stats = await fs.stat(this.currentLogFile);
            
            if (stats.size >= this.maxFileSize) {
                // Rotate log file with full timestamp
                const now = new Date();
                const timestamp = now.toISOString()
                    .replace(/T/, '-')
                    .replace(/\..+/, '')
                    .replace(/:/g, '-');
                const rotatedFile = path.join(this.logDir, `galaxy-strike-${timestamp}.log`);
                
                await fs.rename(this.currentLogFile, rotatedFile);
                
                // Clean up old log files
                await this.cleanupOldLogs();
                
                // Create new current log file with new timestamp
                const newTimestamp = new Date().toISOString()
                    .replace(/T/, '-')
                    .replace(/\..+/, '')
                    .replace(/:/g, '-');
                this.currentLogFile = path.join(this.logDir, `galaxy-strike-${newTimestamp}.log`);
                
                await this.writeToFile('=== Log Rotated ===\n');
            }
        } catch (error) {
            // File might not exist yet, which is fine
            if (error.code !== 'ENOENT') {
                console.error('Failed to rotate log:', error);
            }
        }
    }
    
    async cleanupOldLogs() {
        if (this.isRenderer) return;
        
        const fs = require('fs').promises;
        const path = require('path');
        
        try {
            const files = await fs.readdir(this.logDir);
            const logFiles = files
                .filter(file => file.startsWith('galaxy-strike-') && file.endsWith('.log'))
                .map(file => ({
                    name: file,
                    path: path.join(this.logDir, file)
                }));
            
            if (logFiles.length > this.maxLogFiles) {
                // Get file stats and sort by modification time
                const filesWithStats = await Promise.all(
                    logFiles.map(async file => {
                        const stats = await fs.stat(file.path);
                        return { ...file, mtime: stats.mtime };
                    })
                );
                
                filesWithStats.sort((a, b) => b.mtime - a.mtime);
                
                // Delete oldest files
                const filesToDelete = filesWithStats.slice(this.maxLogFiles);
                for (const file of filesToDelete) {
                    await fs.unlink(file.path);
                }
            }
        } catch (error) {
            console.error('Failed to cleanup old logs:', error);
        }
    }
    
    formatMessage(level, message, data = null) {
        const timestamp = new Date().toISOString();
        const dataStr = data ? ` | Data: ${JSON.stringify(data)}` : '';
        return `[${timestamp}] [${level}] ${message}${dataStr}\n`;
    }
    
    shouldLog(level) {
        const currentLevel = this.levels[this.logLevel] || 2;
        const messageLevel = this.levels[level] || 2;
        return messageLevel <= currentLevel;
    }
    
    async log(level, message, data = null) {
        if (!this.shouldLog(level)) return;
        
        if (this.isRenderer && window.electronAPI) {
            // Send to main process via IPC - ensure data is serializable
            try {
                const serializableData = data ? this.makeSerializable(data) : null;
                window.electronAPI.log(level, message, serializableData);
            } catch (error) {
                console.error('Failed to send log to main process:', error);
                // Fallback to console
                console.log(`[${level}] ${message}`, data || '');
            }
        } else {
            // Main process logging
            const formattedMessage = this.formatMessage(level, message, data);
            await this.writeToFile(formattedMessage);
            console.log(`[${level}] ${message}`, data || '');
        }
    }
    
    makeSerializable(obj) {
        try {
            // Convert to JSON and back to ensure it's serializable
            return JSON.parse(JSON.stringify(obj));
        } catch (error) {
            // If not serializable, convert to string representation
            return {
                type: 'non-serializable',
                toString: obj.toString ? obj.toString() : String(obj),
                constructor: obj.constructor ? obj.constructor.name : 'Unknown'
            };
        }
    }
    
    async error(message, data = null) {
        await this.log('error', message, data);
        console.error(`[ERROR] ${message}`, data || '');
    }
    
    async warn(message, data = null) {
        await this.log('warn', message, data);
        console.warn(`[WARN] ${message}`, data || '');
    }
    
    async info(message, data = null) {
        await this.log('info', message, data);
        console.info(`[INFO] ${message}`, data || '');
    }
    
    async debug(message, data = null) {
        await this.log('debug', message, data);
        console.debug(`[DEBUG] ${message}`, data || '');
    }
    
    async gameEvent(eventType, details) {
        const message = `Game Event: ${eventType}`;
        await this.info(message, details);
    }
    
    // Timing methods
    startTimer(name) {
        this.timers.set(name, performance.now());
    }
    
    endTimer(name) {
        const startTime = this.timers.get(name);
        if (startTime) {
            const duration = performance.now() - startTime;
            this.timers.delete(name);
            return duration;
        }
        return 0;
    }
    
    async timeAsync(name, asyncFunction) {
        this.startTimer(name);
        try {
            const result = await asyncFunction();
            const duration = this.endTimer(name);
            await this.info(`${name} completed`, { duration: `${duration.toFixed(2)}ms` });
            return result;
        } catch (error) {
            const duration = this.endTimer(name);
            await this.error(`${name} failed`, { duration: `${duration.toFixed(2)}ms`, error: error.message });
            throw error;
        }
    }
    
    async playerAction(action, details) {
        const message = `Player Action: ${action}`;
        await this.info(message, details);
    }
    
    async systemEvent(system, event, details) {
        const message = `System Event: ${system} - ${event}`;
        await this.info(message, details);
    }
    
    async errorEvent(error, context = null) {
        const message = `Error Event: ${error.message || error}`;
        const data = {
            stack: error.stack,
            context: context
        };
        await this.error(message, data);
    }
    
    setLogLevel(level) {
        if (this.levels.hasOwnProperty(level)) {
            this.logLevel = level;
            this.info(`Log level changed to: ${level}`);
        }
    }
    
    getLogInfo() {
        return {
            isInitialized: this.isInitialized,
            isRenderer: this.isRenderer,
            logDirectory: this.logDir,
            currentLogFile: this.currentLogFile,
            logLevel: this.logLevel
        };
    }
}

// Export singleton instance
const logger = new Logger();

// For Node.js environments
if (typeof module !== 'undefined' && module.exports) {
    module.exports = logger;
}

// For browser environments
if (typeof window !== 'undefined') {
    window.logger = logger;
}
