import { _electron as electron, ElectronApplication, Page } from '@playwright/test';
import * as path from 'path';

/**
 * ElectronTestHarness - Manages Electron app lifecycle for smoke tests
 * 
 * Responsibilities:
 * - Launch actual compiled Electron app
 * - Wait for renderer window to open
 * - Provide access to main process and renderer page
 * - Clean shutdown
 */
export class ElectronTestHarness {
  private app: ElectronApplication | null = null;
  private mainWindow: Page | null = null;

  /**
   * Launch Electron app and wait for main window
   * 
   * @throws Error if app fails to launch or window doesn't open
   */
  async launch(): Promise<void> {
    // Path to the built Electron app entry point
    const electronEntryPath = path.join(__dirname, '../../../apps/companion/dist/main/main.cjs');

    // Launch Electron app with the compiled entry file
    // Note: Playwright may have compatibility issues with certain Electron versions
    // regarding --remote-debugging-port flag
    const launchOptions: any = {
      args: [electronEntryPath],
      env: {
        ...Object.fromEntries(Object.entries(process.env).filter(([_, v]) => v !== undefined)),
        NODE_ENV: 'test',
      },
    };
    if (process.env.ELECTRON_EXECUTABLE_PATH) {
      launchOptions.executablePath = process.env.ELECTRON_EXECUTABLE_PATH;
    }
    this.app = await electron.launch(launchOptions);

    // Wait for first window (renderer process)
    this.mainWindow = await this.app.firstWindow({
      timeout: 10_000,
    });

    // Wait for React to render
    await this.mainWindow.waitForLoadState('domcontentloaded');
  }

  /**
   * Get the main renderer window
   */
  getMainWindow(): Page {
    if (!this.mainWindow) {
      throw new Error('Main window not available. Did you call launch()?');
    }
    return this.mainWindow;
  }

  /**
   * Get the Electron app instance for IPC testing
   */
  getApp(): ElectronApplication {
    if (!this.app) {
      throw new Error('Electron app not available. Did you call launch()?');
    }
    return this.app;
  }

  /**
   * Clean shutdown of Electron app
   */
  async close(): Promise<void> {
    if (this.app) {
      await this.app.close();
      this.app = null;
      this.mainWindow = null;
    }
  }
}