const { ProxyAgent } = require('undici');

/**
 * These tests verify the proxy wrapper behavior for GeminiImageGen.
 * Instead of loading the full module (which has many dependencies),
 * we directly test the wrapper logic that would be applied.
 */
describe('GeminiImageGen Proxy Configuration', () => {
  let originalEnv;
  let originalFetch;

  beforeAll(() => {
    originalEnv = { ...process.env };
    originalFetch = globalThis.fetch;
  });

  beforeEach(() => {
    process.env = { ...originalEnv };
    globalThis.fetch = originalFetch;
  });

  afterEach(() => {
    process.env = originalEnv;
    globalThis.fetch = originalFetch;
  });

  /**
   * Simulates the proxy wrapper that GeminiImageGen applies at module load.
   * This is the same logic from GeminiImageGen.js lines 30-42.
   */
  function applyProxyWrapper() {
    if (process.env.PROXY) {
      const _originalFetch = globalThis.fetch;
      const proxyAgent = new ProxyAgent(process.env.PROXY);

      globalThis.fetch = function (url, options = {}) {
        const urlString = url.toString();
        if (urlString.includes('googleapis.com')) {
          options = { ...options, dispatcher: proxyAgent };
        }
        return _originalFetch.call(this, url, options);
      };
    }
  }

  it('should wrap globalThis.fetch when PROXY env is set', () => {
    process.env.PROXY = 'http://proxy.example.com:8080';

    const fetchBeforeWrap = globalThis.fetch;

    applyProxyWrapper();

    expect(globalThis.fetch).not.toBe(fetchBeforeWrap);
  });

  it('should not wrap globalThis.fetch when PROXY env is not set', () => {
    delete process.env.PROXY;

    const fetchBeforeWrap = globalThis.fetch;

    applyProxyWrapper();

    expect(globalThis.fetch).toBe(fetchBeforeWrap);
  });

  it('should add dispatcher to googleapis.com URLs', async () => {
    process.env.PROXY = 'http://proxy.example.com:8080';

    let capturedOptions = null;
    const mockFetch = jest.fn((url, options) => {
      capturedOptions = options;
      return Promise.resolve({ ok: true });
    });
    globalThis.fetch = mockFetch;

    applyProxyWrapper();

    await globalThis.fetch('https://generativelanguage.googleapis.com/v1/models', {});

    expect(capturedOptions).toBeDefined();
    expect(capturedOptions.dispatcher).toBeInstanceOf(ProxyAgent);
  });

  it('should not add dispatcher to non-googleapis.com URLs', async () => {
    process.env.PROXY = 'http://proxy.example.com:8080';

    let capturedOptions = null;
    const mockFetch = jest.fn((url, options) => {
      capturedOptions = options;
      return Promise.resolve({ ok: true });
    });
    globalThis.fetch = mockFetch;

    applyProxyWrapper();

    await globalThis.fetch('https://api.openai.com/v1/images', {});

    expect(capturedOptions).toBeDefined();
    expect(capturedOptions.dispatcher).toBeUndefined();
  });

  it('should preserve existing options when adding dispatcher', async () => {
    process.env.PROXY = 'http://proxy.example.com:8080';

    let capturedOptions = null;
    const mockFetch = jest.fn((url, options) => {
      capturedOptions = options;
      return Promise.resolve({ ok: true });
    });
    globalThis.fetch = mockFetch;

    applyProxyWrapper();

    const customHeaders = { 'X-Custom-Header': 'test' };
    await globalThis.fetch('https://aiplatform.googleapis.com/v1/models', {
      headers: customHeaders,
      method: 'POST',
    });

    expect(capturedOptions).toBeDefined();
    expect(capturedOptions.dispatcher).toBeInstanceOf(ProxyAgent);
    expect(capturedOptions.headers).toEqual(customHeaders);
    expect(capturedOptions.method).toBe('POST');
  });
});
