import { describe, it, expect, vi, beforeEach } from 'vitest';

interface PortStub {
  name: string;
  postMessage: ReturnType<typeof vi.fn>;
  onMessage: { addListener: ReturnType<typeof vi.fn> };
  onDisconnect: { addListener: (fn: () => void) => void };
  disconnect: ReturnType<typeof vi.fn>;
}

interface ChromeStub {
  runtime: {
    id: string;
    sendMessage: ReturnType<typeof vi.fn>;
    onMessage: { addListener: ReturnType<typeof vi.fn> };
    connect: () => PortStub;
  };
}

interface GlobalWithChrome {
  chrome?: ChromeStub;
  MediaRecorder?: { isTypeSupported: (mime: string) => boolean };
}

describe('port reconnect', () => {
  beforeEach(() => {
    vi.resetModules();
    (globalThis as unknown as GlobalWithChrome).MediaRecorder = {
      isTypeSupported: vi.fn().mockReturnValue(true),
    };
  });

  it('connects on module load', async () => {
    let connectCount = 0;
    const disconnectListeners: Array<() => void> = [];
    const stub: ChromeStub = {
      runtime: {
        id: 'ext-id-test',
        sendMessage: vi.fn(),
        onMessage: { addListener: vi.fn() },
        connect: () => {
          connectCount++;
          return {
            name: 'video-keepalive',
            postMessage: vi.fn(),
            onMessage: { addListener: vi.fn() },
            onDisconnect: {
              addListener: (fn: () => void) => disconnectListeners.push(fn),
            },
            disconnect: vi.fn(),
          };
        },
      },
    };
    (globalThis as unknown as GlobalWithChrome).chrome = stub;
    await import('../../src/offscreen/recorder');
    expect(connectCount).toBe(1);
  });

  it('reconnects when port disconnects', async () => {
    let connectCount = 0;
    const disconnectListeners: Array<() => void> = [];
    const stub: ChromeStub = {
      runtime: {
        id: 'ext-id-test',
        sendMessage: vi.fn(),
        onMessage: { addListener: vi.fn() },
        connect: () => {
          connectCount++;
          return {
            name: 'video-keepalive',
            postMessage: vi.fn(),
            onMessage: { addListener: vi.fn() },
            onDisconnect: {
              addListener: (fn: () => void) => disconnectListeners.push(fn),
            },
            disconnect: vi.fn(),
          };
        },
      },
    };
    (globalThis as unknown as GlobalWithChrome).chrome = stub;
    await import('../../src/offscreen/recorder');
    expect(connectCount).toBe(1);
    // Fire the disconnect — module should reconnect
    disconnectListeners.forEach((fn) => fn());
    expect(connectCount).toBeGreaterThanOrEqual(2);
  });
});
