import { Page, ConsoleMessage } from '@playwright/test';

export interface ConsoleError {
  type: 'error' | 'warning' | 'pageerror';
  message: string;
  location?: string;
  timestamp: Date;
}

/**
 * ConsoleMonitor - Aggregates and tracks all console output
 * 
 * Purpose: Catch ANY runtime errors during Electron app lifecycle
 * 
 * Critical Detections:
 * - "Module has been externalized for browser compatibility"
 * - "__dirname is not defined"
 * - "require is not defined"
 * - Any uncaught exceptions
 */
export class ConsoleMonitor {
  private errors: ConsoleError[] = [];
  private warnings: ConsoleError[] = [];
  private isMonitoring = false;

  /**
   * Start monitoring console output on the page
   */
  startMonitoring(page: Page): void {
    if (this.isMonitoring) {
      return;
    }

    // Monitor console.error calls
    page.on('console', (msg: ConsoleMessage) => {
      if (msg.type() === 'error') {
        this.errors.push({
          type: 'error',
          message: msg.text(),
          location: msg.location()?.url,
          timestamp: new Date(),
        });
      } else if (msg.type() === 'warning') {
        this.warnings.push({
          type: 'warning',
          message: msg.text(),
          location: msg.location()?.url,
          timestamp: new Date(),
        });
      }
    });

    // Monitor uncaught exceptions
    page.on('pageerror', (error: Error) => {
      const errorObj: ConsoleError = {
        type: 'pageerror',
        message: error.message,
        timestamp: new Date(),
      };
      if (error.stack) {
        errorObj.location = error.stack;
      }
      this.errors.push(errorObj);
    });

    this.isMonitoring = true;
  }

  /**
   * Check if any errors were detected
   */
  hasErrors(): boolean {
    return this.errors.length > 0;
  }

  /**
   * Get all detected errors
   */
  getErrors(): ConsoleError[] {
    return [...this.errors];
  }

  /**
   * Get all detected warnings
   */
  getWarnings(): ConsoleError[] {
    return [...this.warnings];
  }

  /**
   * Format errors for test output
   */
  formatErrors(): string {
    if (this.errors.length === 0) {
      return 'No errors detected';
    }

    const lines = ['Console errors detected during test:', ''];
    
    this.errors.forEach((error, index) => {
      lines.push(`${index + 1}. [${error.type}] ${error.message}`);
      if (error.location) {
        lines.push(`   Location: ${error.location}`);
      }
      lines.push('');
    });

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

  /**
   * Check for specific browser context errors
   */
  hasBrowserContextErrors(): boolean {
    const contextErrorPatterns = [
      /has been externalized for browser compatibility/i,
      /__dirname is not defined/i,
      /require is not defined/i,
      /Cannot access .* in client code/i,
    ];

    return this.errors.some(error => 
      contextErrorPatterns.some(pattern => pattern.test(error.message))
    );
  }

  /**
   * Reset monitoring state
   */
  reset(): void {
    this.errors = [];
    this.warnings = [];
  }
}