import { chromium, type Browser, type BrowserContext, type ConsoleMessage, type Page } from 'playwright';
import { logger } from '../../lib/logger.js';

export interface BrowserSession {
  browser: Browser;
  context: BrowserContext;
  page: Page;
  consoleLogs: ConsoleLog[];
}

export interface ConsoleLog {
  type: 'log' | 'error' | 'warn' | 'info' | 'debug';
  text: string;
  location?: string;
  time: string;
}

class BrowserManager {
  private session: BrowserSession | null = null;

  async getSession(headless = true): Promise<BrowserSession> {
    if (this.session) return this.session;

    try {
      const browser = await chromium.launch({ headless });
      const context = await browser.newContext({ viewport: { width: 1280, height: 720 } });
      const page = await context.newPage();
      const consoleLogs: ConsoleLog[] = [];

      page.on('console', (msg) => {
        const location = msg.location();
        consoleLogs.push({
          type: msg.type() as ConsoleLog['type'],
          text: msg.text(),
          location: `${location.url}:${location.lineNumber}:${location.columnNumber}`,
          time: new Date().toISOString(),
        });
      });

      page.on('pageerror', (error) => {
        consoleLogs.push({
          type: 'error',
          text: `Page error: ${error.message}`,
          time: new Date().toISOString(),
        });
      });

      page.on('requestfailed', (request) => {
        consoleLogs.push({
          type: 'error',
          text: `Network request failed: ${request.method()} ${request.url()}`,
          time: new Date().toISOString(),
        });
      });

      this.session = { browser, context, page, consoleLogs };
      return this.session;
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      if (message.includes("Executable doesn't exist") || message.includes('browserType.launch')) {
        throw new Error(
          'Playwright Chromium browser is not installed. ' +
            'Install it with: npx playwright install chromium',
        );
      }
      throw error;
    }
  }

  async close(): Promise<void> {
    if (!this.session) return;
    try {
      await this.session.browser.close();
    } catch (error) {
      logger.error('error closing browser', { error: error instanceof Error ? error.message : error });
    } finally {
      this.session = null;
    }
  }

  resetLogs(): void {
    if (this.session) {
      this.session.consoleLogs.length = 0;
    }
  }
}

export const browserManager = new BrowserManager();
