const { app, BrowserWindow, Menu, shell, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs');
const logger = require('./js/core/Logger');

console.log('[MAIN PROCESS] Electron main process starting...');
console.log('[MAIN PROCESS] Node.js version:', process.version);
console.log('[MAIN PROCESS] Electron version:', process.versions.electron);
console.log('[MAIN PROCESS] Platform:', process.platform);
console.log('[MAIN PROCESS] Current working directory:', process.cwd());

// Keep a global reference of the window object
let mainWindow;

function createWindow() {
    console.log('[MAIN PROCESS] createWindow() called');
    
    try {
        console.log('[MAIN PROCESS] Creating BrowserWindow...');
        // Create the browser window
        mainWindow = new BrowserWindow({
            width: 1200,
            height: 832, // 800 + 32px for custom title bar
            minWidth: 1200,
            minHeight: 832,
            maxWidth: 1200,
            maxHeight: 832,
            resizable: false,
            frame: false,
            titleBarStyle: 'hidden',
            webPreferences: {
                nodeIntegration: true,
                contextIsolation: false,
                enableRemoteModule: true,
                webSecurity: true
            },
            icon: path.join(__dirname, 'assets/icon.png'),
            show: false, // Don't show until ready-to-show
            title: 'Galaxy Strike Online'
        });

        console.log('[MAIN PROCESS] BrowserWindow created successfully');
        console.log('[MAIN PROCESS] Loading index.html...');

        // Load the index.html file
        mainWindow.loadFile('index.html');

        console.log('[MAIN PROCESS] index.html loaded, setting up electronAPI...');

        // Set up electronAPI after DOM is ready
        mainWindow.webContents.on('dom-ready', () => {
            console.log('[MAIN PROCESS] DOM is ready, setting up electronAPI...');
            mainWindow.webContents.executeJavaScript(`
                console.log('[RENDERER] Setting up electronAPI...');
                window.electronAPI = {
                    minimizeWindow: () => require('electron').ipcRenderer.send('minimize-window'),
                    closeWindow: () => require('electron').ipcRenderer.send('close-window'),
                    toggleFullscreen: () => require('electron').ipcRenderer.send('toggle-fullscreen'),
                    log: (level, message, data) => require('electron').ipcRenderer.send('log-message', { level, message, data }),
                    createSaveFolders: (saveSlots) => require('electron').ipcRenderer.invoke('create-save-folders', saveSlots),
                    testFileAccess: (slotPath) => require('electron').ipcRenderer.invoke('test-file-access', slotPath),
                    saveGame: (slot, saveData) => require('electron').ipcRenderer.invoke('save-game', slot, saveData),
                    loadGame: (slot) => require('electron').ipcRenderer.invoke('load-game', slot),
                    getPath: (name) => require('electron').ipcRenderer.invoke('get-path', name),
                    deleteSaveFile: (slot) => require('electron').ipcRenderer.invoke('delete-save-file', slot)
                };
                console.log('[RENDERER] electronAPI setup completed');
            `).then(() => {
                console.log('[MAIN PROCESS] electronAPI setup completed');
            }).catch((error) => {
                console.error('[MAIN PROCESS] Failed to setup electronAPI:', error);
            });
        });

        // Show window when ready
        mainWindow.once('ready-to-show', () => {
            console.log('[MAIN PROCESS] Window ready-to-show event fired');
            mainWindow.show();
        });

        // Open DevTools in development
        if (process.argv.includes('--dev')) {
            console.log('[MAIN PROCESS] Opening DevTools...');
            mainWindow.webContents.openDevTools();
        }

        // Handle window closed
        mainWindow.on('closed', () => {
            console.log('[MAIN PROCESS] Window closed event fired');
            mainWindow = null;
        });

        // Handle renderer process crashes
        mainWindow.webContents.on('render-process-gone', (event, details) => {
            console.error('[MAIN PROCESS] Renderer process crashed:', details);
            console.error('[MAIN PROCESS] Crash reason:', details.reason);
            console.error('[MAIN PROCESS] Exit code:', details.exitCode);
        });

        // Handle renderer process unresponsive
        mainWindow.webContents.on('unresponsive', () => {
            console.warn('[MAIN PROCESS] Renderer process unresponsive');
        });

        // Handle renderer process responsive again
        mainWindow.webContents.on('responsive', () => {
            console.log('[MAIN PROCESS] Renderer process responsive again');
        });

        // Handle console messages from renderer
        mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
            console.log(`[RENDERER CONSOLE] [${level}] ${message} (line: ${line}, source: ${sourceId})`);
        });

        // Handle page load errors
        mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
            console.error('[MAIN PROCESS] Page failed to load:', errorCode, errorDescription, validatedURL);
        });

        // Handle page load success
        mainWindow.webContents.on('did-finish-load', () => {
            console.log('[MAIN PROCESS] Page finished loading');
        });

        // Handle DOM ready
        mainWindow.webContents.on('dom-ready', () => {
            console.log('[MAIN PROCESS] DOM is ready');
        });

        // Handle external links
        mainWindow.webContents.setWindowOpenHandler(({ url }) => {
            console.log('[MAIN PROCESS] External link requested:', url);
            shell.openExternal(url);
            return { action: 'deny' };
        });
        
        console.log('[MAIN PROCESS] createWindow() completed successfully');
        
    } catch (error) {
        console.error('[MAIN PROCESS] Error in createWindow():', error);
        console.error('[MAIN PROCESS] Error stack:', error.stack);
    }
}

// IPC handlers for save operations
ipcMain.handle('create-save-folders', async (event, saveSlots) => {
    console.log('[MAIN PROCESS] create-save-folders called with saveSlots:', saveSlots);
    try {
        const userDataPath = app.getPath('userData');
        console.log('[MAIN PROCESS] userDataPath:', userDataPath);
        const savesDir = path.join(userDataPath, 'saves');
        console.log('[MAIN PROCESS] savesDir:', savesDir);
        
        // Create main saves directory
        if (!fs.existsSync(savesDir)) {
            console.log('[MAIN PROCESS] Creating saves directory:', savesDir);
            fs.mkdirSync(savesDir, { recursive: true });
            console.log('[MAIN PROCESS] Saves directory created successfully');
        } else {
            console.log('[MAIN PROCESS] Saves directory already exists');
        }
        
        const paths = {
            base: savesDir,
            slots: []
        };
        
        // Create save slot directories
        for (let i = 1; i <= saveSlots; i++) {
            const slotDir = path.join(savesDir, `slot${i}`);
            console.log(`[MAIN PROCESS] Checking/creating slot ${i} directory:`, slotDir);
            if (!fs.existsSync(slotDir)) {
                console.log(`[MAIN PROCESS] Creating slot ${i} directory`);
                fs.mkdirSync(slotDir, { recursive: true });
                
                // Create initial save info file
                const saveInfo = {
                    slot: i,
                    created: new Date().toISOString(),
                    version: '1.0.0',
                    exists: false
                };
                
                const infoPath = path.join(slotDir, 'saveinfo.json');
                fs.writeFileSync(infoPath, JSON.stringify(saveInfo, null, 2));
                console.log(`[MAIN PROCESS] Created save info for slot ${i}`);
            } else {
                console.log(`[MAIN PROCESS] Slot ${i} directory already exists`);
            }
            paths.slots.push(slotDir);
        }
        
        console.log('[MAIN PROCESS] Save folders created successfully, returning paths:', paths);
        return { success: true, paths };
    } catch (error) {
        console.error('[MAIN PROCESS] Failed to create save folders:', error);
        return { success: false, error: error.message };
    }
});

ipcMain.handle('test-file-access', async (event, slotPath) => {
    try {
        const testFile = path.join(slotPath, 'access_test.txt');
        fs.writeFileSync(testFile, 'test');
        fs.unlinkSync(testFile);
        return { success: true };
    } catch (error) {
        return { success: false, error: error.message };
    }
});

ipcMain.handle('save-game', async (event, slot, saveData) => {
    try {
        const userDataPath = app.getPath('userData');
        const savesDir = path.join(userDataPath, 'saves');
        const slotDir = path.join(savesDir, `slot${slot}`);
        
        // Save game data
        const saveFilePath = path.join(slotDir, 'save.json');
        fs.writeFileSync(saveFilePath, JSON.stringify(saveData, null, 2));
        
        // Update save info
        const infoPath = path.join(slotDir, 'saveinfo.json');
        const saveInfo = {
            slot: slot,
            created: new Date().toISOString(),
            lastSaved: new Date().toISOString(),
            version: '1.0.0',
            exists: true,
            playTime: saveData.gameTime || 0
        };
        fs.writeFileSync(infoPath, JSON.stringify(saveInfo, null, 2));
        
        return { success: true };
    } catch (error) {
        console.error('Failed to save game:', error);
        return { success: false, error: error.message };
    }
});

ipcMain.handle('load-game', async (event, slot) => {
    try {
        const userDataPath = app.getPath('userData');
        const savesDir = path.join(userDataPath, 'saves');
        const slotDir = path.join(savesDir, `slot${slot}`);
        const saveFilePath = path.join(slotDir, 'save.json');
        
        if (fs.existsSync(saveFilePath)) {
            const saveContent = fs.readFileSync(saveFilePath, 'utf8');
            const saveData = JSON.parse(saveContent);
            return { success: true, data: saveData };
        } else {
            return { success: false, error: 'Save file not found' };
        }
    } catch (error) {
        console.error('Failed to load game:', error);
        return { success: false, error: error.message };
    }
});

ipcMain.handle('get-path', async (event, name) => {
    try {
        return app.getPath(name);
    } catch (error) {
        return null;
    }
});

ipcMain.handle('delete-save-file', async (event, slot) => {
    console.log('[MAIN PROCESS] delete-save-file called for slot:', slot);
    try {
        const userDataPath = app.getPath('userData');
        const savesDir = path.join(userDataPath, 'saves');
        const slotDir = path.join(savesDir, `slot${slot}`);
        const saveFilePath = path.join(slotDir, 'save.json');
        const infoFilePath = path.join(slotDir, 'saveinfo.json');
        
        console.log('[MAIN PROCESS] Attempting to delete save files from:', slotDir);
        
        let deletedFiles = [];
        
        // Delete save file if it exists
        if (fs.existsSync(saveFilePath)) {
            console.log('[MAIN PROCESS] Deleting save file:', saveFilePath);
            fs.unlinkSync(saveFilePath);
            deletedFiles.push('save.json');
        }
        
        // Delete save info file if it exists
        if (fs.existsSync(infoFilePath)) {
            console.log('[MAIN PROCESS] Deleting save info file:', infoFilePath);
            fs.unlinkSync(infoFilePath);
            deletedFiles.push('saveinfo.json');
        }
        
        // Create empty save info file to indicate slot is empty
        const saveInfo = {
            slot: slot,
            created: new Date().toISOString(),
            version: '1.0.0',
            exists: false,
            deleted: new Date().toISOString()
        };
        fs.writeFileSync(infoFilePath, JSON.stringify(saveInfo, null, 2));
        
        console.log('[MAIN PROCESS] Successfully deleted save files for slot', slot, ':', deletedFiles);
        return { success: true, deletedFiles };
    } catch (error) {
        console.error('[MAIN PROCESS] Failed to delete save file:', error);
        return { success: false, error: error.message };
    }
});

// IPC handlers for window controls
// Handle logging from renderer process
ipcMain.on('log-message', async (event, { level, message, data }) => {
    try {
        switch (level) {
            case 'error':
                await logger.error(message, data);
                break;
            case 'warn':
                await logger.warn(message, data);
                break;
            case 'info':
                await logger.info(message, data);
                break;
            case 'debug':
                await logger.debug(message, data);
                break;
            default:
                await logger.info(message, data);
        }
    } catch (error) {
        console.error('Failed to log message from renderer:', error);
        // Fallback to console logging to prevent infinite loops
        console.log(`[${level}] ${message}`, data || '');
    }
});

ipcMain.on('minimize-window', () => {
    if (mainWindow) {
        mainWindow.minimize();
    }
});

ipcMain.on('close-window', () => {
    if (mainWindow) {
        mainWindow.close();
    }
});

ipcMain.on('toggle-fullscreen', () => {
    if (mainWindow) {
        const isFullscreen = mainWindow.isFullScreen();
        if (isFullscreen) {
            mainWindow.setFullScreen(false);
            mainWindow.setSize(1200, 832);
            mainWindow.center();
        } else {
            mainWindow.setFullScreen(true);
        }
    }
});

// This method will be called when Electron has finished initialization
app.whenReady().then(async () => {
    console.log('[MAIN PROCESS] Electron app ready, starting initialization...');
    
    try {
        // Initialize logger with app data path
        console.log('[MAIN PROCESS] Initializing logger...');
        await logger.initialize(app.getPath('userData'));
        console.log('[MAIN PROCESS] Logger initialized');
        
        await logger.info('Galaxy Strike Online application starting');
        console.log('[MAIN PROCESS] Logger info message sent');
        
        console.log('[MAIN PROCESS] Creating main window...');
        createWindow();

        app.on('activate', () => {
            console.log('[MAIN PROCESS] Activate event fired');
            // On macOS it's common to re-create a window in the app when the dock icon is clicked
            if (BrowserWindow.getAllWindows().length === 0) {
                console.log('[MAIN PROCESS] No windows exist, creating new window');
                createWindow();
            }
        });
        
        console.log('[MAIN PROCESS] App initialization completed successfully');
        
    } catch (error) {
        console.error('[MAIN PROCESS] Error during app initialization:', error);
        console.error('[MAIN PROCESS] Error stack:', error.stack);
    }
}).catch((error) => {
    console.error('[MAIN PROCESS] Error in app.whenReady():', error);
    console.error('[MAIN PROCESS] Error stack:', error.stack);
});

// Quit when all windows are closed
app.on('window-all-closed', () => {
    // On macOS it's common for applications and their menu bar to stay active
    if (process.platform !== 'darwin') {
        logger.info('Application shutting down');
        app.quit();
    }
});

// Handle uncaught exceptions
process.on('uncaughtException', async (error) => {
    console.error('[MAIN PROCESS] Uncaught Exception:', error);
    console.error('[MAIN PROCESS] Uncaught Exception stack:', error.stack);
    
    try {
        if (logger && typeof logger.errorEvent === 'function') {
            await logger.errorEvent(error, 'Uncaught Exception in Main Process');
        }
    } catch (logError) {
        console.error('[MAIN PROCESS] Failed to log uncaught exception:', logError);
    }
    
    console.error('[MAIN PROCESS] Application will continue running despite uncaught exception');
});

// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
    console.error('[MAIN PROCESS] Unhandled Promise Rejection at:', promise, 'reason:', reason);
    console.error('[MAIN PROCESS] Rejection reason stack:', reason.stack);
});

// Handle unhandled rejections
process.on('unhandledRejection', async (reason, promise) => {
    // Avoid logging the logging system's own errors to prevent infinite loops
    if (reason && reason.message && reason.message.includes('object could not be cloned')) {
        console.warn('IPC cloning error detected - this is expected during logger initialization');
        return;
    }
    
    await logger.error('Unhandled Rejection', { reason: reason.toString(), promise: promise.toString() });
    console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

// Security: Prevent new window creation
app.on('web-contents-created', (event, contents) => {
    contents.on('new-window', (event, navigationUrl) => {
        event.preventDefault();
        shell.openExternal(navigationUrl);
    });
});
