import { ElectronApplication } from '@playwright/test';

type IpcHandlerResult = {
  error?: string;
  [key: string]: unknown;
};

export interface IPCTestResult {
  channel: string;
  success: boolean;
  error?: string;
  duration: number;
}

/**
 * IPCVerifier - Tests IPC channel contracts
 * 
 * Purpose: Verify main <-> renderer communication works
 * Scope: Core IPC channels required for app functionality
 */
export class IPCVerifier {
  constructor(private app: ElectronApplication) {}

  /**
   * Test checkAuth IPC channel
   */
  async testCheckAuth(): Promise<IPCTestResult> {
    const start = Date.now();
    const channel = 'auth:check';

    try {
      const result = await this.app.evaluate(
        async ({ ipcMain }: { ipcMain: { listeners: (channel: string) => unknown[] } }) => {
          return new Promise((resolve) => {
            // Simulate IPC invoke handler by calling the first registered handler for the channel
            const handlers = ipcMain.listeners('auth:check') || [];
            const handler = handlers[0] as
              | ((event: unknown, ...args: unknown[]) => unknown | Promise<unknown>)
              | undefined;
 
            if (!handler) {
              resolve({ error: 'Handler not registered' });
            } else {
              // Invoke the handler similar to ipcMain.handle invocation signature
              // (event, ...args) => Promise
              const mockEvent: unknown = {};
              Promise.resolve(handler(mockEvent))
                .then((res: unknown) => resolve(res))
                .catch((err: unknown) =>
                  resolve({
                    error:
                      err && err instanceof Error && err.message
                        ? err.message
                        : String(err),
                  }),
                );
            }
          });
        },
      );

      const typed: IpcHandlerResult = result as IpcHandlerResult;

      const resultObj: IPCTestResult = {
        channel,
        success: !typed.error,
        duration: Date.now() - start,
      };
      if (typed.error) {
        resultObj.error = typed.error;
      }
      return resultObj;
    } catch (error) {
      return {
        channel,
        success: false,
        error: error instanceof Error ? error.message : String(error),
        duration: Date.now() - start,
      };
    }
  }

  /**
   * Test getBrowserMode IPC channel
   */
  async testGetBrowserMode(): Promise<IPCTestResult> {
    const start = Date.now();
    const channel = 'browser-mode:get';

    try {
      const result = await this.app.evaluate(
        async ({ ipcMain }: { ipcMain: { listeners: (channel: string) => unknown[] } }) => {
          return new Promise((resolve) => {
            const handlers = ipcMain.listeners('browser-mode:get') || [];
            const handler = handlers[0] as
              | ((event: unknown, ...args: unknown[]) => unknown | Promise<unknown>)
              | undefined;
 
            if (!handler) {
              resolve({ error: 'Handler not registered' });
            } else {
              const mockEvent: unknown = {};
              Promise.resolve(handler(mockEvent))
                .then((res: unknown) => resolve(res))
                .catch((err: unknown) =>
                  resolve({
                    error:
                      err && err instanceof Error && err.message
                        ? err.message
                        : String(err),
                  }),
                );
            }
          });
        },
      );

      const typed: IpcHandlerResult = result as IpcHandlerResult;

      const resultObj: IPCTestResult = {
        channel,
        success: !typed.error,
        duration: Date.now() - start,
      };
      if (typed.error) {
        resultObj.error = typed.error;
      }
      return resultObj;
    } catch (error) {
      return {
        channel,
        success: false,
        error: error instanceof Error ? error.message : String(error),
        duration: Date.now() - start,
      };
    }
  }

  /**
   * Test startAutomationSession IPC channel contract
   */
  async testStartAutomationSession(): Promise<IPCTestResult> {
    const start = Date.now();
    const channel = 'start-automation';

    try {
      const result = await this.app.evaluate(
        async ({ ipcMain }: { ipcMain: { listeners: (channel: string) => unknown[] } }) => {
          return new Promise((resolve) => {
            const handlers = ipcMain.listeners('start-automation') || [];
            const handler = handlers[0] as
              | ((
                  event: unknown,
                  payload: { sessionName: string; mode: string },
                ) => unknown | Promise<unknown>)
              | undefined;
            
            if (!handler) {
              resolve({ error: 'Handler not registered' });
            } else {
              // Test with mock data
              const mockEvent: unknown = {};
              Promise.resolve(
                handler(mockEvent, { sessionName: 'test', mode: 'test' }),
              )
                .then((res: unknown) => resolve(res))
                .catch((err: unknown) =>
                  resolve({
                    error:
                      err && err instanceof Error && err.message
                        ? err.message
                        : String(err),
                  }),
                );
            }
          });
        },
      );

      const typed: IpcHandlerResult = result as IpcHandlerResult;

      const resultObj: IPCTestResult = {
        channel,
        success: !typed.error,
        duration: Date.now() - start,
      };
      if (typed.error) {
        resultObj.error = typed.error;
      }
      return resultObj;
    } catch (error) {
      return {
        channel,
        success: false,
        error: error instanceof Error ? error.message : String(error),
        duration: Date.now() - start,
      };
    }
  }

  /**
   * Run all IPC tests and return results
   */
  async verifyAllChannels(): Promise<IPCTestResult[]> {
    return Promise.all([
      this.testCheckAuth(),
      this.testGetBrowserMode(),
      this.testStartAutomationSession(),
    ]);
  }

  /**
   * Format IPC test results for output
   */
  static formatResults(results: IPCTestResult[]): string {
    const lines = ['IPC Channel Verification:', ''];
    
    results.forEach(result => {
      const status = result.success ? '✓' : '✗';
      lines.push(`${status} ${result.channel} (${result.duration}ms)`);
      if (result.error) {
        lines.push(`  Error: ${result.error}`);
      }
    });

    return lines.join('\n');
  }
}