import { expect, test } from "@playwright/test";

test.describe("WebSocket E2E Tests", () => {
  test("should connect to WebSocket server", async ({ page }) => {
    // Create a simple test page that can test Socket.IO functionality
    await page.setContent(`
      <html>
        <head>
          <script src="https://cdn.socket.io/4.8.3/socket.io.min.js"></script>
          <script>
            window.testResults = {};

            function connectSocketIO() {
              const socket = io('http://localhost:3001');

              socket.on('connect', () => {
                window.testResults.connected = true;
                socket.disconnect();
              });

              socket.on('connect_error', () => {
                window.testResults.connected = false;
              });

              socket.on('disconnect', () => {
                window.testResults.disconnected = true;
              });
            }

            window.connectSocketIO = connectSocketIO;
          </script>
        </head>
        <body>
          <div id="test">Socket.IO Test</div>
        </body>
      </html>
    `);

    // Execute the Socket.IO connection test
    await page.evaluate(() => {
      (window as any).connectSocketIO();
    });

    // Wait for connection result
    await page.waitForFunction(
      () => (window as any).testResults.connected !== undefined
    );

    const results = await page.evaluate(() => (window as any).testResults);
    expect(results.connected).toBe(true);
  });

  test("should handle Socket.IO connection", async ({ page }) => {
    // Test Socket.IO connection using a script that loads socket.io-client
    await page.setContent(`
      <html>
        <head>
          <script src="https://cdn.socket.io/4.8.3/socket.io.min.js"></script>
          <script>
            window.testResults = {};

            function testSocketIO() {
              const socket = io('http://localhost:3001');

              socket.on('connect', () => {
                window.testResults.connected = true;
                socket.disconnect();
              });

              socket.on('connect_error', () => {
                window.testResults.connected = false;
              });

              socket.on('disconnect', () => {
                window.testResults.disconnected = true;
              });
            }

            window.testSocketIO = testSocketIO;
          </script>
        </head>
        <body>
          <div id="test">Socket.IO Test</div>
        </body>
      </html>
    `);

    // Execute the Socket.IO connection test
    await page.evaluate(() => {
      (window as any).testSocketIO();
    });

    // Wait for connection result
    await page.waitForFunction(
      () => (window as any).testResults.connected !== undefined,
      { timeout: 5000 }
    );

    const results = await page.evaluate(() => (window as any).testResults);
    expect(results.connected).toBe(true);
  });

  test("should handle room operations via Socket.IO", async ({ page }) => {
    await page.setContent(`
      <html>
        <head>
          <script src="https://cdn.socket.io/4.8.3/socket.io.min.js"></script>
          <script>
            window.testResults = { events: [] };

            function testRoomOperations() {
              const socket = io('http://localhost:3001');

              socket.on('connect', () => {
                window.testResults.connected = true;

                // Join a room
                socket.emit('join', { room: 'testRoom' });
              });

              socket.on('joined', (data) => {
                window.testResults.events.push({ type: 'joined', data });

                // Leave the room
                socket.emit('leave', { room: 'testRoom' });
              });

              socket.on('left', (data) => {
                window.testResults.events.push({ type: 'left', data });
                socket.disconnect();
              });
            }

            window.testRoomOperations = testRoomOperations;
          </script>
        </head>
        <body>
          <div id="test">Room Operations Test</div>
        </body>
      </html>
    `);

    // Execute the room operations test
    await page.evaluate(() => {
      (window as any).testRoomOperations();
    });

    // Wait for events
    await page.waitForFunction(
      () => (window as any).testResults.events.length >= 2,
      { timeout: 5000 }
    );

    const results = await page.evaluate(() => (window as any).testResults);
    expect(results.connected).toBe(true);
    expect(results.events).toContainEqual({
      type: "joined",
      data: { room: "testRoom" }
    });
    expect(results.events).toContainEqual({
      type: "left",
      data: { room: "testRoom" }
    });
  });

  test("should receive taskUpdate events", async ({ page }) => {
    // Test that client can listen for taskUpdate events
    // Note: This test validates WebSocket event subscription, not actual event emission
    // which depends on service logic and may not occur in e2e test environment

    await page.setContent(`
      <html>
        <head>
          <script src="https://cdn.socket.io/4.8.3/socket.io.min.js"></script>
          <script>
            window.testResults = { events: [], connected: false };

            function testTaskUpdates() {
              const socket = io('http://localhost:3001');

              socket.on('connect', () => {
                window.testResults.connected = true;
              });

              socket.on('taskUpdate', (data) => {
                window.testResults.events.push({ type: 'taskUpdate', data });
              });

              // Store socket reference
              window.testSocket = socket;

              // Disconnect after 5 seconds regardless of events
              setTimeout(() => {
                socket.disconnect();
                window.testResults.completed = true;
              }, 5000);
            }

            window.testTaskUpdates = testTaskUpdates;
          </script>
        </head>
        <body>
          <div id="test">Task Update Test</div>
        </body>
      </html>
    `);

    // Execute the test
    await page.evaluate(() => {
      (window as any).testTaskUpdates();
    });

    // Wait for test completion
    await page.waitForFunction(
      () => (window as any).testResults.completed === true
    );

    const results = await page.evaluate(() => (window as any).testResults);
    expect(results.connected).toBe(true);
    // Event reception is optional - just validate connection and subscription capability
    console.log("TaskUpdate events received:", results.events.length);
  });

  test("should receive fileUpdate events", async ({ page }) => {
    await page.setContent(`
      <html>
        <head>
          <script src="https://cdn.socket.io/4.8.3/socket.io.min.js"></script>
          <script>
            window.testResults = { events: [], connected: false };

            function testFileUpdates() {
              const socket = io('http://localhost:3001');

              socket.on('connect', () => {
                window.testResults.connected = true;
              });

              socket.on('fileUpdate', (data) => {
                window.testResults.events.push({ type: 'fileUpdate', data });
              });

              // Store socket reference
              window.testSocket = socket;

              // Disconnect after a short time
              setTimeout(() => {
                socket.disconnect();
              }, 2000);
            }

            window.testFileUpdates = testFileUpdates;
          </script>
        </head>
        <body>
          <div id="test">File Update Test</div>
        </body>
      </html>
    `);

    // Execute the file update test
    await page.evaluate(() => {
      (window as any).testFileUpdates();
    });

    // Wait for connection and disconnection
    await page.waitForFunction(
      () => (window as any).testResults.connected === true,
      { timeout: 5000 }
    );

    await page.waitForFunction(
      () =>
        (window as any).testSocket &&
        (window as any).testSocket.disconnected === true,
      { timeout: 5000 }
    );

    const results = await page.evaluate(() => (window as any).testResults);
    expect(results.connected).toBe(true);
    // File events are optional - just validate connection capability
    console.log(
      "No fileUpdate event received - this may be expected if watcher is not active"
    );
  });

  test("should receive watcherUpdate events", async ({ page }) => {
    await page.setContent(`
      <html>
        <head>
          <script src="https://cdn.socket.io/4.8.3/socket.io.min.js"></script>
          <script>
            window.testResults = { events: [], connected: false };

            function testWatcherUpdates() {
              const socket = io('http://localhost:3001');

              socket.on('connect', () => {
                window.testResults.connected = true;
              });

              socket.on('watcherUpdate', (data) => {
                window.testResults.events.push({ type: 'watcherUpdate', data });
              });

              // Store socket reference
              window.testSocket = socket;

              // Disconnect after a short time
              setTimeout(() => {
                socket.disconnect();
              }, 2000);
            }

            window.testWatcherUpdates = testWatcherUpdates;
          </script>
        </head>
        <body>
          <div id="test">Watcher Update Test</div>
        </body>
      </html>
    `);

    // Execute the watcher update test
    await page.evaluate(() => {
      (window as any).testWatcherUpdates();
    });

    // Wait for connection and disconnection
    await page.waitForFunction(
      () => (window as any).testResults.connected === true,
      { timeout: 5000 }
    );

    await page.waitForFunction(
      () =>
        (window as any).testSocket &&
        (window as any).testSocket.disconnected === true,
      { timeout: 5000 }
    );

    const results = await page.evaluate(() => (window as any).testResults);
    expect(results.connected).toBe(true);
    // Watcher events are optional - just validate connection capability
    console.log(
      "No watcherUpdate event received - this may be expected if watcher is not active"
    );
  });
});
