const { app, BrowserWindow, ipcMain, safeStorage } = require('electron')
const path = require('path')
import { log } from './logger'
import { LogLevel, MachineAction, MachineResponse } from '../types/electron'
import { Machine } from '../renderer/types'

// Temporary storage for demo
const machinesStore: Record<string, Machine> = {
  'test-vm-01': {
    id: 'test-vm-01',
    name: 'Test VM 1',
    status: 'running',
    os: 'Windows 10',
    ip: '192.168.1.100',
    hypervisor: 'VMware',
    specs: {
      cpu: '4 cores',
      ram: '8GB',
      disk: '256GB'
    },
    testLinks: [
      { name: 'RDP', url: 'rdp://192.168.1.100' },
      { name: 'Web Console', url: 'https://192.168.1.100:8080' }
    ],
    logs: [
      { timestamp: new Date().toISOString(), message: 'System started', level: 'info' }
    ]
  }
};

// Logging event interface
interface LogEvent {
  level: LogLevel;
  tag: string;
  message: string;
  context?: Record<string, unknown>;
}

function createWindow() {
  log.info('startup', 'Creating main window...')
  
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, '..', 'preload.js'),
    },
  })

  // Additional CSP configuration via session - DISABLED for debugging
  /*
  mainWindow.webContents.session.webRequest.onHeadersReceived((details: any, callback: any) => {
    const isDev = process.env.NODE_ENV === 'development';
    
    const cspValue = isDev 
      ? "default-src 'self' 'unsafe-inline' 'unsafe-eval'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost:* ws://localhost:*; style-src 'self' 'unsafe-inline' http://localhost:*; connect-src 'self' http://localhost:* https://localhost:* ws://localhost:* wss://localhost:*; frame-src 'self' http://localhost:* https://localhost:*; img-src 'self' data: blob: http://localhost:*; font-src 'self' data: http://localhost:*; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';"
      : "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://mc.exbytestudios.com; frame-src 'self' https://mc.exbytestudios.com; img-src 'self' data: blob:; font-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';";

    callback({
      responseHeaders: {
        ...details.responseHeaders,
        'Content-Security-Policy': [cspValue]
      }
    });
  });
  */

  // In development, load from Vite dev server
  const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL;
  log.debug('startup', 'VITE_DEV_SERVER_URL:', { url: VITE_DEV_SERVER_URL })
  
  if (VITE_DEV_SERVER_URL) {
    log.info('startup', 'Loading from dev server', { url: VITE_DEV_SERVER_URL })
    mainWindow.loadURL(VITE_DEV_SERVER_URL);
    mainWindow.webContents.openDevTools();
  } else {
    const indexPath = path.join(__dirname, '..', 'renderer', 'index.html')
    log.info('startup', 'Loading from file', { path: indexPath })
    console.log('Attempting to load file:', indexPath);
    mainWindow.loadFile(indexPath);
  }

  // Add page load debugging
  mainWindow.webContents.on('did-finish-load', () => {
    log.info('startup', 'Page finished loading');
    console.log('Page loaded');
  });

  mainWindow.webContents.on('did-fail-load', (_event: any, errorCode: any, errorDescription: any) => {
    log.error('startup', 'Page failed to load', { errorCode, errorDescription });
    console.error('Page load error:', errorCode, errorDescription);
  });

  // Force open DevTools for debugging
  mainWindow.webContents.openDevTools();

  // Handle window close
  mainWindow.on('closed', () => {
    log.info('window', 'Main window closed, quitting application')
    app.quit();
  })
}

// This method will be called when Electron has finished initialization
app.whenReady().then(() => {
  log.info('startup', 'Application ready, initializing...')
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      log.info('window', 'No windows available, creating new window')
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    log.info('window', 'All windows closed, quitting application')
    app.quit()
  }
})

// Handle logging events from renderer process
ipcMain.on('log-event', (_event: any, { level, tag, message, context }: LogEvent) => {
  log[level](tag, message, context)
})

// IPC event handlers

// Connect to machine
ipcMain.handle('connect-to-machine', async (_event: any, machine: Machine): Promise<MachineResponse> => {
  log.info('connect-machine', 'Connection request received', { 
    machineId: machine.id,
    machineName: machine.name 
  });
  
  try {
    // TODO: Real connection logic will be added later
    return { 
      success: true, 
      message: 'Connection successful',
      details: { machineId: machine.id }
    };
  } catch (error) {
    log.error('connect-machine', 'Connection failed', {
      machineId: machine.id,
      error: error instanceof Error ? error.message : String(error)
    });
    throw error;
  }
});

// Control machine state
ipcMain.handle('control-machine', async (_event: any, { machineId, action }: { machineId: string; action: MachineAction }): Promise<MachineResponse> => {
  log.info('control-machine', `Machine ${action} requested`, { machineId, action });
  
  try {
    const machine = machinesStore[machineId];
    if (!machine) {
      throw new Error(`Machine ${machineId} not found`);
    }

    // Simulate state change
    switch (action) {
      case 'start':
        machine.status = 'running';
        machine.logs.unshift({
          timestamp: new Date().toISOString(),
          message: 'Machine started',
          level: 'info'
        });
        break;
      case 'stop':
        machine.status = 'stopped';
        machine.logs.unshift({
          timestamp: new Date().toISOString(),
          message: 'Machine stopped',
          level: 'info'
        });
        break;
      case 'restart':
        machine.status = 'stopped';
        machine.logs.unshift({
          timestamp: new Date().toISOString(),
          message: 'Machine restarting',
          level: 'info'
        });
        setTimeout(() => {
          machine.status = 'running';
          machine.logs.unshift({
            timestamp: new Date().toISOString(),
            message: 'Machine restarted successfully',
            level: 'info'
          });
          log.info('control-machine', 'Machine restarted', { machineId });
        }, 2000);
        break;
    }

    return {
      success: true,
      message: `Machine ${action} successful`,
      details: { machineId, newStatus: machine.status }
    };
  } catch (error) {
    log.error('control-machine', `Machine ${action} failed`, {
      machineId,
      error: error instanceof Error ? error.message : String(error)
    });
    throw error;
  }
});

// Get machine status
ipcMain.handle('get-machine-status', async (_event: any, machineId: string): Promise<MachineResponse> => {
  log.debug('get-machine-status', 'Status requested', { machineId });
  
  const machine = machinesStore[machineId];
  if (!machine) {
    throw new Error(`Machine ${machineId} not found`);
  }

  return {
    success: true,
    message: 'Status retrieved',
    status: machine.status
  };
});

// Get machine list
ipcMain.handle('get-machine-list', async (): Promise<MachineResponse> => {
  log.debug('get-machine-list', 'Machine list requested');
  
  return {
    success: true,
    message: 'Machine list retrieved',
    machines: Object.values(machinesStore)
  };
});

// FIXED: Secure storage (Electron safeStorage) for XSS protection

// Check encryption availability
ipcMain.handle('is-encryption-available', async (): Promise<boolean> => {
  try {
    return safeStorage.isEncryptionAvailable();
  } catch (error) {
    log.error('safe-storage', 'Failed to check encryption availability', { 
      error: error instanceof Error ? error.message : String(error) 
    });
    return false;
  }
});

// Encrypt data
ipcMain.handle('encrypt-data', async (_event: any, plaintext: string): Promise<string> => {
  try {
    if (!safeStorage.isEncryptionAvailable()) {
      throw new Error('Encryption not available on this platform');
    }
    
    const buffer = safeStorage.encryptString(plaintext);
    const encrypted = buffer.toString('base64');
    
    log.debug('safe-storage', 'Data encrypted successfully', { 
      plaintextLength: plaintext.length,
      encryptedLength: encrypted.length 
    });
    
    return encrypted;
  } catch (error) {
    log.error('safe-storage', 'Failed to encrypt data', { 
      error: error instanceof Error ? error.message : String(error) 
    });
    throw error;
  }
});

// Decrypt data
ipcMain.handle('decrypt-data', async (_event: any, encrypted: string): Promise<string> => {
  try {
    if (!safeStorage.isEncryptionAvailable()) {
      throw new Error('Encryption not available on this platform');
    }
    
    const buffer = Buffer.from(encrypted, 'base64');
    const plaintext = safeStorage.decryptString(buffer);
    
    log.debug('safe-storage', 'Data decrypted successfully', { 
      encryptedLength: encrypted.length,
      plaintextLength: plaintext.length 
    });
    
    return plaintext;
  } catch (error) {
    log.error('safe-storage', 'Failed to decrypt data', { 
      error: error instanceof Error ? error.message : String(error) 
    });
    throw error;
  }
}); 