import { Page, Browser } from 'playwright';
import { DebugState, DOMSnapshot, NetworkRequest } from '../types';
import { LogTruncator } from '../utils/log-truncator';
import { FlutterDebugEngine } from './flutter-debug-engine';
import { ProblemDebugEngine } from './problem-debug-engine';
import { NextJSDebugEngine } from './nextjs-debug-engine';
import { ServerFrameworkDebugEngine } from './server-framework-debug-engine';
import { MetaFrameworkDebugEngine } from './meta-framework-debug-engine';
import { tidewave, TidewaveCapabilities } from '../utils/tidewave-integration';

export class LocalDebugEngine {
  private browser?: Browser;
  private page?: Page;
  private consoleMessages: Array<{ type: string; text: string; timestamp: Date }> = [];
  private networkRequests: NetworkRequest[] = [];
  private mockedResponses: Map<string, { 
    status: number; 
    body: any; 
    headers?: Record<string, string>;
    delay?: number;
  }> = new Map();
  private flutterEngine?: FlutterDebugEngine;
  private problemEngine: ProblemDebugEngine;
  private nextjsEngine?: NextJSDebugEngine;
  private serverFrameworkEngine?: ServerFrameworkDebugEngine;
  private metaFrameworkEngine?: MetaFrameworkDebugEngine;
  private tidewaveCapabilities?: TidewaveCapabilities;
  
  constructor() {
    this.problemEngine = new ProblemDebugEngine();
  }
  
  async attachToPage(page: Page): Promise<void> {
    this.page = page;
    
    // Set up console monitoring
    page.on('console', (msg) => {
      this.consoleMessages.push({
        type: msg.type(),
        text: msg.text(),
        timestamp: new Date()
      });
    });
    
    // Set up network monitoring and mocking
    page.on('request', (request) => {
      this.networkRequests.push({
        url: request.url(),
        method: request.method(),
        headers: request.headers(),
        timestamp: new Date(),
        status: 'pending'
      });
    });
    
    page.on('response', (response) => {
      const index = this.networkRequests.findIndex(
        req => req.url === response.url() && req.status === 'pending'
      );
      if (index !== -1) {
        this.networkRequests[index] = {
          ...this.networkRequests[index],
          status: 'complete',
          responseStatus: response.status(),
          responseHeaders: response.headers()
        };
      }
    });
    
    // Set up route interception for mocking
    await this.setupNetworkMocking();
    
    // Attach problem detection engine
    await this.problemEngine.attachToPage(page);
    
    // Detect and attach framework-specific engines
    await this.attachFrameworkEngines(page);
  }
  
  private async setupNetworkMocking(): Promise<void> {
    if (!this.page) return;
    
    await this.page.route('**/*', async (route) => {
      const url = route.request().url();
      
      // Check if we have a mock for this URL
      for (const [pattern, mockData] of this.mockedResponses) {
        if (this.matchesPattern(url, pattern)) {
          // Apply delay if specified
          if (mockData.delay) {
            await new Promise(resolve => setTimeout(resolve, mockData.delay));
          }
          
          // Return mocked response
          await route.fulfill({
            status: mockData.status,
            headers: mockData.headers || {},
            body: typeof mockData.body === 'string' 
              ? mockData.body 
              : JSON.stringify(mockData.body),
            contentType: mockData.headers?.['content-type'] || 'application/json'
          });
          
          console.log(`Mocked response for ${url}`);
          return;
        }
      }
      
      // Continue with normal request
      await route.continue();
    });
  }
  
  private matchesPattern(url: string, pattern: string): boolean {
    // Support wildcards and simple patterns
    const regexPattern = pattern
      .replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escape special chars
      .replace(/\*/g, '.*'); // Convert * to .*
    
    return new RegExp(regexPattern).test(url);
  }
  
  async captureState(): Promise<DebugState> {
    if (!this.page) {
      throw new Error('No page attached');
    }
    
    const [localStorage, sessionStorage, cookies, url] = await Promise.all([
      this.captureStorage('localStorage'),
      this.captureStorage('sessionStorage'),
      this.page.context().cookies(),
      this.page.url()
    ]);
    
    return {
      url,
      localStorage,
      sessionStorage,
      cookies,
      timestamp: new Date()
    };
  }
  
  private async captureStorage(type: 'localStorage' | 'sessionStorage'): Promise<Record<string, any>> {
    if (!this.page) return {};
    
    try {
      return await this.page.evaluate((storageType) => {
        const storage = (window as any)[storageType];
        const items: Record<string, any> = {};
        
        for (let i = 0; i < storage.length; i++) {
          const key = storage.key(i);
          if (key) {
            try {
              items[key] = JSON.parse(storage.getItem(key) || '');
            } catch {
              items[key] = storage.getItem(key);
            }
          }
        }
        
        return items;
      }, type);
    } catch (error) {
      return {};
    }
  }
  
  async captureDOMSnapshot(): Promise<DOMSnapshot> {
    if (!this.page) {
      throw new Error('No page attached');
    }
    
    const snapshot = await this.page.evaluate(() => {
      const serializeNode = (node: Element): any => {
        const attributes: Record<string, string> = {};
        for (const attr of Array.from(node.attributes) as Attr[]) {
          attributes[attr.name] = attr.value;
        }
        
        return {
          tagName: node.tagName.toLowerCase(),
          attributes,
          children: Array.from(node.children).map(serializeNode),
          textContent: node.textContent?.trim() || ''
        };
      };
      
      return {
        html: document.documentElement.outerHTML,
        structure: serializeNode(document.documentElement),
        timestamp: new Date().toISOString()
      };
    });
    
    return {
      ...snapshot,
      timestamp: new Date(snapshot.timestamp)
    };
  }
  
  async injectDebuggingCode(code: string): Promise<any> {
    if (!this.page) {
      throw new Error('No page attached');
    }
    
    return await this.page.evaluate(code);
  }
  
  async inspectElement(selector: string): Promise<{
    exists: boolean;
    visible?: boolean;
    properties?: Record<string, any>;
    computedStyles?: Record<string, string>;
  }> {
    if (!this.page) {
      throw new Error('No page attached');
    }
    
    return await this.page.evaluate((sel) => {
      const element = document.querySelector(sel);
      if (!element) {
        return { exists: false };
      }
      
      const rect = element.getBoundingClientRect();
      const styles = (window as any).getComputedStyle(element);
      const computedStyles: Record<string, string> = {};
      
      // Get key computed styles
      ['display', 'visibility', 'opacity', 'position', 'top', 'left', 'width', 'height'].forEach(prop => {
        computedStyles[prop] = styles.getPropertyValue(prop);
      });
      
      return {
        exists: true,
        visible: rect.width > 0 && rect.height > 0 && styles.display !== 'none' && styles.visibility !== 'hidden',
        properties: {
          tagName: element.tagName,
          id: element.id,
          className: element.className,
          textContent: element.textContent?.trim(),
          innerHTML: element.innerHTML.substring(0, 200),
          rect: {
            top: rect.top,
            left: rect.left,
            width: rect.width,
            height: rect.height
          }
        },
        computedStyles
      };
    }, selector);
  }
  
  async simulateUserAction(action: string, selector?: string, value?: any): Promise<void> {
    if (!this.page) {
      throw new Error('No page attached');
    }
    
    switch (action) {
      case 'click':
        if (selector) {
          await this.page.click(selector);
        }
        break;
        
      case 'type':
        if (selector && value) {
          await this.page.fill(selector, value);
        }
        break;
        
      case 'hover':
        if (selector) {
          await this.page.hover(selector);
        }
        break;
        
      case 'screenshot':
        await this.page.screenshot({ 
          path: value || 'debug-screenshot.png',
          fullPage: true 
        });
        break;
        
      case 'reload':
        await this.page.reload();
        break;
        
      default:
        throw new Error(`Unknown action: ${action}`);
    }
  }
  
  getConsoleMessages(
    filter?: { type?: string; since?: Date; maxTokens?: number }
  ): Array<{ type: string; text: string; timestamp: Date }> {
    let messages = [...this.consoleMessages];
    
    if (filter?.type) {
      messages = messages.filter(msg => msg.type === filter.type);
    }
    
    if (filter?.since) {
      messages = messages.filter(msg => msg.timestamp > filter.since!);
    }
    
    // Apply intelligent truncation if needed
    if (filter?.maxTokens) {
      // First try grouping similar messages
      messages = LogTruncator.groupSimilarLogs(messages);
      
      // Then truncate to fit token limit
      messages = LogTruncator.truncateLogs(messages, {
        maxTokens: filter.maxTokens,
        preserveLatest: true,
        prioritizeErrors: true
      });
    }
    
    return messages;
  }
  
  getNetworkRequests(filter?: { status?: string; pattern?: string }): NetworkRequest[] {
    let requests = [...this.networkRequests];
    
    if (filter?.status) {
      requests = requests.filter(req => req.status === filter.status);
    }
    
    if (filter?.pattern) {
      const regex = new RegExp(filter.pattern);
      requests = requests.filter(req => regex.test(req.url));
    }
    
    return requests;
  }
  
  async findReactComponents(): Promise<Array<{ name: string; props: any; state: any }>> {
    if (!this.page) {
      throw new Error('No page attached');
    }
    
    return await this.page.evaluate(() => {
      const components: Array<{ name: string; props: any; state: any }> = [];
      
      // Find React fiber nodes
      const findReactFiber = (element: Element): any => {
        const keys = Object.keys(element);
        const fiberKey = keys.find(key => key.startsWith('__reactFiber'));
        return fiberKey ? (element as any)[fiberKey] : null;
      };
      
      // Walk the DOM and find React components
      const walkDOM = (element: Element) => {
        const fiber = findReactFiber(element);
        if (fiber && fiber.elementType && typeof fiber.elementType === 'function') {
          components.push({
            name: fiber.elementType.name || 'Anonymous',
            props: fiber.memoizedProps || {},
            state: fiber.memoizedState || {}
          });
        }
        
        Array.from(element.children).forEach(walkDOM);
      };
      
      walkDOM(document.body);
      return components;
    }).catch(() => []);
  }
  
  async findPhoenixLiveViewState(): Promise<any> {
    if (!this.page) {
      throw new Error('No page attached');
    }
    
    return await this.page.evaluate(() => {
      // Look for Phoenix LiveView hooks
      const liveSocket = (window as any).liveSocket;
      if (!liveSocket) return null;
      
      const views: any[] = [];
      
      // Find all LiveView elements
      document.querySelectorAll('[data-phx-view]').forEach((element: any) => {
        const phxView = element.getAttribute('data-phx-view');
        const phxSession = element.getAttribute('data-phx-session');
        
        views.push({
          id: phxView,
          session: phxSession,
          element: {
            id: element.id,
            className: element.className,
            tagName: element.tagName
          }
        });
      });
      
      return {
        connected: liveSocket.isConnected(),
        views,
        hooks: Object.keys((window as any).Hooks || {})
      };
    }).catch(() => null);
  }
  
  async detectFramework(page: Page): Promise<string> {
    this.page = page;
    
    // Check for meta-frameworks first (they might also be React/Vue/etc)
    this.metaFrameworkEngine = new MetaFrameworkDebugEngine();
    await this.metaFrameworkEngine.attachToPage(page);
    const metaFrameworkInfo = this.metaFrameworkEngine.getFrameworkInfo();
    if (metaFrameworkInfo?.framework) {
      return metaFrameworkInfo.framework;
    }
    
    // Check for Next.js (if not detected by meta-framework engine)
    this.nextjsEngine = new NextJSDebugEngine();
    const isNextJS = await this.nextjsEngine.detectNextJS(page);
    if (isNextJS) {
      await this.nextjsEngine.attachToPage(page);
      return 'nextjs';
    }
    
    // Check for server frameworks
    this.serverFrameworkEngine = new ServerFrameworkDebugEngine();
    const serverFramework = await this.serverFrameworkEngine.detectServerFramework(page);
    if (serverFramework) {
      await this.serverFrameworkEngine.attachToPage(page);
      return serverFramework;
    }
    
    // Check for Flutter Web
    this.flutterEngine = new FlutterDebugEngine();
    const isFlutter = await this.flutterEngine.detectFlutterWeb(page);
    if (isFlutter) {
      // Try to connect to Flutter DevTools
      const port = await this.flutterEngine.findDebugPort(page);
      if (port) {
        await this.flutterEngine.connect(port);
      }
      return 'flutter-web';
    }
    
    // Check for Phoenix LiveView
    const phoenixState = await this.findPhoenixLiveViewState();
    if (phoenixState) return 'phoenix';
    
    // Check for React
    const reactComponents = await this.findReactComponents();
    if (reactComponents.length > 0) return 'react';
    
    // Check for Vue
    const hasVue = await page.evaluate(() => {
      return !!(window as any).Vue || document.querySelector('[data-v-]');
    });
    if (hasVue) return 'vue';
    
    // Check for Angular
    const hasAngular = await page.evaluate(() => {
      return !!(window as any).ng || document.querySelector('[ng-version]');
    });
    if (hasAngular) return 'angular';
    
    // Check for Svelte
    const hasSvelte = await page.evaluate(() => {
      return document.querySelector('[data-svelte]') !== null;
    });
    if (hasSvelte) return 'svelte';
    
    return 'unknown';
  }
  
  async injectDebugging(page: Page, framework: string): Promise<void> {
    this.page = page;
    
    // Inject framework-agnostic debugging
    await page.addInitScript(() => {
      (window as any).__AI_DEBUG__ = {
        events: [],
        recordEvent: function(type: string, data: any) {
          this.events.push({
            type,
            data,
            timestamp: new Date().toISOString()
          });
        }
      };
      
      // Monitor console
      const originalLog = console.log;
      const originalError = console.error;
      const originalWarn = console.warn;
      
      console.log = function(...args) {
        (window as any).__AI_DEBUG__.recordEvent('console.log', { args });
        return originalLog.apply(console, args);
      };
      
      console.error = function(...args) {
        (window as any).__AI_DEBUG__.recordEvent('console.error', { args });
        return originalError.apply(console, args);
      };
      
      console.warn = function(...args) {
        (window as any).__AI_DEBUG__.recordEvent('console.warn', { args });
        return originalWarn.apply(console, args);
      };
      
      // Monitor clicks
      document.addEventListener('click', (e: any) => {
        const target = e.target as HTMLElement;
        (window as any).__AI_DEBUG__.recordEvent('click', {
          selector: target.tagName + (target.id ? '#' + target.id : '') + (target.className ? '.' + target.className.split(' ').join('.') : ''),
          text: target.textContent?.substring(0, 50)
        });
      }, true);
    });
    
    // Framework-specific instrumentation
    if (framework === 'phoenix') {
      await page.addInitScript(() => {
        const checkLiveSocket = setInterval(() => {
          const liveSocket = (window as any).liveSocket;
          if (liveSocket) {
            clearInterval(checkLiveSocket);
            
            // Monitor LiveView events
            const originalPush = liveSocket.push;
            liveSocket.push = function(event: any) {
              (window as any).__AI_DEBUG__.recordEvent('phoenix.push', { event });
              return originalPush.apply(this, arguments);
            };
          }
        }, 100);
      });
    }
  }
  
  async monitorEvents(page: Page, duration: number): Promise<any[]> {
    const startTime = Date.now();
    const events: any[] = [];
    
    // Collect events for the specified duration
    while (Date.now() - startTime < duration * 1000) {
      const pageEvents = await page.evaluate(() => {
        const aiDebug = (window as any).__AI_DEBUG__;
        if (!aiDebug) return [];
        const currentEvents = [...aiDebug.events];
        aiDebug.events = []; // Clear collected events
        return currentEvents;
      });
      
      events.push(...pageEvents);
      await page.waitForTimeout(1000); // Check every second
    }
    
    return events;
  }
  
  basicAnalysis(events: any[]): any {
    const analysis: any = {
      mostActiveElement: null,
      performanceScore: 100,
      errorRate: 0
    };
    
    // Find most clicked element
    const clickCounts: Record<string, number> = {};
    events.filter(e => e.type === 'click').forEach(e => {
      const selector = e.data.selector;
      clickCounts[selector] = (clickCounts[selector] || 0) + 1;
    });
    
    if (Object.keys(clickCounts).length > 0) {
      analysis.mostActiveElement = Object.entries(clickCounts)
        .sort(([,a], [,b]) => b - a)[0][0];
    }
    
    // Calculate error rate
    const errorCount = events.filter(e => e.type === 'console.error' || e.type === 'error').length;
    analysis.errorRate = events.length > 0 ? Math.round((errorCount / events.length) * 100) : 0;
    
    // Adjust performance score based on errors
    analysis.performanceScore = Math.max(0, 100 - (analysis.errorRate * 2));
    
    return analysis;
  }
  
  async simulateAction(page: Page, action: string, selector: string, value?: string): Promise<any> {
    const startTime = Date.now();
    let success = true;
    let error = null;
    let description = '';
    
    try {
      switch (action) {
        case 'click':
          await page.click(selector);
          description = `Clicked element ${selector}`;
          break;
        case 'type':
          await page.fill(selector, value || '');
          description = `Typed "${value}" into ${selector}`;
          break;
        case 'submit':
          await page.press(selector, 'Enter');
          description = `Submitted form at ${selector}`;
          break;
        case 'scroll':
          await page.hover(selector);
          await page.mouse.wheel(0, parseInt(value || '100'));
          description = `Scrolled ${value || 100}px at ${selector}`;
          break;
        case 'hover':
          await page.hover(selector);
          description = `Hovered over ${selector}`;
          break;
      }
    } catch (e) {
      success = false;
      error = e instanceof Error ? e.message : String(e);
      description = `Failed to ${action} ${selector}`;
    }
    
    return {
      success,
      error,
      description,
      duration: Date.now() - startTime
    };
  }
  
  async captureRecentEvents(page: Page, duration: number): Promise<any[]> {
    await page.waitForTimeout(duration);
    
    return await page.evaluate(() => {
      const aiDebug = (window as any).__AI_DEBUG__;
      if (!aiDebug) return [];
      return [...aiDebug.events];
    });
  }
  
  async extractPageState(page: Page): Promise<any> {
    const state = await this.captureState();
    const dom = await this.captureDOMSnapshot();
    const framework = await this.detectFramework(page);
    
    let frameworkState = null;
    if (framework === 'phoenix') {
      frameworkState = await this.findPhoenixLiveViewState();
    } else if (framework === 'react') {
      frameworkState = await this.findReactComponents();
    }
    
    return {
      ...state,
      dom,
      framework,
      frameworkState
    };
  }
  
  generateBasicReport(session: any): any {
    const errorEvents = session.events.filter((e: any) => e.type === 'error' || e.type === 'console.error');
    const clickEvents = session.events.filter((e: any) => e.type === 'click');
    const networkEvents = session.events.filter((e: any) => e.type === 'networkRequest');
    
    const findings = [];
    
    if (errorEvents.length > 0) {
      findings.push(`Found ${errorEvents.length} errors during session`);
    }
    
    if (clickEvents.length > 10) {
      findings.push(`High user interaction detected (${clickEvents.length} clicks)`);
    }
    
    if (networkEvents.length > 50) {
      findings.push(`Heavy network activity (${networkEvents.length} requests)`);
    }
    
    if (findings.length === 0) {
      findings.push('Session completed without significant issues');
    }
    
    return { findings };
  }
  
  async addNetworkMock(
    urlPattern: string,
    response: {
      status?: number;
      body?: any;
      headers?: Record<string, string>;
      delay?: number;
    }
  ): Promise<void> {
    this.mockedResponses.set(urlPattern, {
      status: response.status || 200,
      body: response.body || {},
      headers: response.headers,
      delay: response.delay
    });
    
    // Re-setup mocking if page is already attached
    if (this.page) {
      await this.setupNetworkMocking();
    }
  }
  
  removeNetworkMock(urlPattern: string): boolean {
    return this.mockedResponses.delete(urlPattern);
  }
  
  clearAllMocks(): void {
    this.mockedResponses.clear();
  }
  
  getMockedUrls(): string[] {
    return Array.from(this.mockedResponses.keys());
  }
  
  // Flutter-specific methods
  async getFlutterWidgetTree(): Promise<any> {
    if (!this.flutterEngine) {
      throw new Error('Flutter engine not initialized');
    }
    return await this.flutterEngine.getWidgetTree();
  }
  
  async getFlutterPerformance(): Promise<any> {
    if (!this.flutterEngine) {
      throw new Error('Flutter engine not initialized');
    }
    return await this.flutterEngine.getPerformanceInfo();
  }
  
  async inspectFlutterWidget(widgetId: string): Promise<any> {
    if (!this.flutterEngine) {
      throw new Error('Flutter engine not initialized');
    }
    return await this.flutterEngine.inspectWidget(widgetId);
  }
  
  async highlightFlutterWidget(widgetId: string): Promise<void> {
    if (!this.flutterEngine) {
      throw new Error('Flutter engine not initialized');
    }
    await this.flutterEngine.highlightWidget(widgetId);
  }
  
  async getFlutterMemoryUsage(): Promise<any> {
    if (!this.flutterEngine) {
      throw new Error('Flutter engine not initialized');
    }
    return await this.flutterEngine.getMemoryUsage();
  }
  
  isFlutterConnected(): boolean {
    return this.flutterEngine !== undefined;
  }
  
  // Problem-focused debugging methods
  async getHydrationIssues(): Promise<any> {
    return await this.problemEngine.getHydrationIssues();
  }
  
  async getBundleAnalysis(): Promise<any> {
    return await this.problemEngine.getBundleAnalysis();
  }
  
  async getRouteChanges(): Promise<any> {
    return await this.problemEngine.getRouteChanges();
  }
  
  async detectCommonProblems(): Promise<any> {
    return await this.problemEngine.detectCommonProblems();
  }
  
  private async attachFrameworkEngines(page: Page): Promise<void> {
    // This is called after framework detection in detectFramework
    // Engines are already attached there
  }
  
  // Next.js specific methods
  async getNextJSPageInfo(): Promise<any> {
    if (!this.nextjsEngine) {
      throw new Error('Next.js engine not initialized');
    }
    return await this.nextjsEngine.getPageInfo();
  }
  
  async getNextJSBuildInfo(): Promise<any> {
    if (!this.nextjsEngine) {
      throw new Error('Next.js engine not initialized');
    }
    return await this.nextjsEngine.getBuildInfo();
  }
  
  async getNextJSHydrationErrors(): Promise<any> {
    if (!this.nextjsEngine) {
      throw new Error('Next.js engine not initialized');
    }
    return await this.nextjsEngine.getHydrationErrors();
  }
  
  async getNextJSImageIssues(): Promise<any> {
    if (!this.nextjsEngine) {
      throw new Error('Next.js engine not initialized');
    }
    return await this.nextjsEngine.getImageOptimizationIssues();
  }
  
  async detectNextJSProblems(): Promise<any> {
    if (!this.nextjsEngine) {
      throw new Error('Next.js engine not initialized');
    }
    return await this.nextjsEngine.detectNextJSProblems();
  }
  
  // Server framework specific methods
  async getTurboEvents(): Promise<any> {
    if (!this.serverFrameworkEngine) {
      throw new Error('Server framework engine not initialized');
    }
    return await this.serverFrameworkEngine.getTurboEvents();
  }
  
  async getStimulusControllers(): Promise<any> {
    if (!this.serverFrameworkEngine) {
      throw new Error('Server framework engine not initialized');
    }
    return await this.serverFrameworkEngine.getStimulusControllers();
  }
  
  async getCSRFIssues(): Promise<any> {
    if (!this.serverFrameworkEngine) {
      throw new Error('Server framework engine not initialized');
    }
    return await this.serverFrameworkEngine.getCSRFIssues();
  }
  
  async detectServerFrameworkProblems(): Promise<any> {
    if (!this.serverFrameworkEngine) {
      throw new Error('Server framework engine not initialized');
    }
    return await this.serverFrameworkEngine.detectServerFrameworkProblems();
  }
  
  async getFormSubmissions(): Promise<any> {
    if (!this.serverFrameworkEngine) {
      throw new Error('Server framework engine not initialized');
    }
    return await this.serverFrameworkEngine.getFormSubmissions();
  }
  
  isNextJSConnected(): boolean {
    return this.nextjsEngine !== undefined;
  }
  
  isServerFrameworkConnected(): boolean {
    return this.serverFrameworkEngine !== undefined;
  }
  
  // Meta-framework specific methods
  async getMetaFrameworkInfo(): Promise<any> {
    return this.metaFrameworkEngine?.getFrameworkInfo();
  }
  
  async getRemixLoaderData(): Promise<any> {
    if (!this.metaFrameworkEngine) {
      throw new Error('Meta-framework engine not initialized');
    }
    return await this.metaFrameworkEngine.getRemixLoaderData();
  }
  
  async getRemixRouteModules(): Promise<any> {
    if (!this.metaFrameworkEngine) {
      throw new Error('Meta-framework engine not initialized');
    }
    return await this.metaFrameworkEngine.getRemixRouteModules();
  }
  
  async getAstroIslands(): Promise<any> {
    if (!this.metaFrameworkEngine) {
      throw new Error('Meta-framework engine not initialized');
    }
    return await this.metaFrameworkEngine.getAstroIslands();
  }
  
  async getNuxtPayload(): Promise<any> {
    if (!this.metaFrameworkEngine) {
      throw new Error('Meta-framework engine not initialized');
    }
    return await this.metaFrameworkEngine.getNuxtPayload();
  }
  
  async getQwikResumability(): Promise<any> {
    if (!this.metaFrameworkEngine) {
      throw new Error('Meta-framework engine not initialized');
    }
    return await this.metaFrameworkEngine.getQwikResumability();
  }
  
  async getViteHMREvents(): Promise<any> {
    if (!this.metaFrameworkEngine) {
      throw new Error('Meta-framework engine not initialized');
    }
    return await this.metaFrameworkEngine.getViteHMREvents();
  }
  
  async detectMetaFrameworkProblems(): Promise<any> {
    if (!this.metaFrameworkEngine) {
      throw new Error('Meta-framework engine not initialized');
    }
    return await this.metaFrameworkEngine.detectMetaFrameworkProblems();
  }
  
  isMetaFrameworkConnected(): boolean {
    return this.metaFrameworkEngine !== undefined;
  }
  
  async cleanup(): Promise<void> {
    if (this.page) {
      await this.page.close();
    }
    if (this.browser) {
      await this.browser.close();
    }
  }
}