import type { Request } from 'express';
import type { Socket } from 'net';
import { extractClientIp } from './client-ip.util';
import { clientIpFixtures } from '@test-fixtures/common/client-ip.fixture';

type RequestOverrides = Partial<Omit<Request, 'socket'>> & {
  socket?: Partial<Socket>;
};

const makeRequest = (overrides: RequestOverrides): Request => {
  const socket = (overrides.socket ?? {}) as Socket;

  return {
    headers: {},
    ...overrides,
    socket,
  } as Request;
};

describe('extractClientIp', () => {
  it('uses the first x-forwarded-for entry when present', () => {
    const req = makeRequest(
      clientIpFixtures.forwardedFor.overrides as RequestOverrides,
    );

    expect(extractClientIp(req)).toBe(clientIpFixtures.forwardedFor.expected);
  });

  it('falls back to req.ip when x-forwarded-for is missing', () => {
    const req = makeRequest(
      clientIpFixtures.requestIp.overrides as RequestOverrides,
    );

    expect(extractClientIp(req)).toBe(clientIpFixtures.requestIp.expected);
  });

  it('falls back to socket remoteAddress when req.ip is empty', () => {
    const req = makeRequest(
      clientIpFixtures.socketIp.overrides as RequestOverrides,
    );

    expect(extractClientIp(req)).toBe(clientIpFixtures.socketIp.expected);
  });
});
