import { isPluggyRequestAuthentic } from './pluggy-webhook.signature';

describe('isPluggyRequestAuthentic (M0 S4 — IP allowlist + secret header)', () => {
  const expectedToken = 'whsec_test_pluggy';
  const allowedIps = ['177.71.238.212'];

  it('accepts an allowlisted IP with a matching secret header', () => {
    expect(
      isPluggyRequestAuthentic({
        ip: '177.71.238.212',
        allowedIps,
        presentedToken: expectedToken,
        expectedToken,
      }),
    ).toBe(true);
  });

  it('rejects a non-allowlisted IP even with a matching token', () => {
    expect(
      isPluggyRequestAuthentic({
        ip: '203.0.113.9',
        allowedIps,
        presentedToken: expectedToken,
        expectedToken,
      }),
    ).toBe(false);
  });

  it('rejects a wrong token even from an allowlisted IP (constant-time compare)', () => {
    expect(
      isPluggyRequestAuthentic({
        ip: '177.71.238.212',
        allowedIps,
        presentedToken: 'totally-wrong-token-value',
        expectedToken,
      }),
    ).toBe(false);
  });

  it('rejects a missing/empty presented or expected token', () => {
    expect(
      isPluggyRequestAuthentic({
        ip: '177.71.238.212',
        allowedIps,
        presentedToken: undefined,
        expectedToken,
      }),
    ).toBe(false);
    expect(
      isPluggyRequestAuthentic({
        ip: '177.71.238.212',
        allowedIps,
        presentedToken: expectedToken,
        expectedToken: '',
      }),
    ).toBe(false);
  });

  it('handles a length mismatch without throwing (returns false)', () => {
    expect(
      isPluggyRequestAuthentic({
        ip: '177.71.238.212',
        allowedIps,
        presentedToken: 'short',
        expectedToken,
      }),
    ).toBe(false);
  });

  it('skips the IP check when allowedIps is empty (header-only mode)', () => {
    expect(
      isPluggyRequestAuthentic({
        ip: '203.0.113.9',
        allowedIps: [],
        presentedToken: expectedToken,
        expectedToken,
      }),
    ).toBe(true);
  });

  it('accepts an IPv4-mapped IPv6 client IP against an IPv4 allowlist entry', () => {
    // Node/Express may surface the client IP as `::ffff:177.71.238.212` when the
    // socket is dual-stack. That must still match the bare IPv4 allowlist entry.
    expect(
      isPluggyRequestAuthentic({
        ip: '::ffff:177.71.238.212',
        allowedIps,
        presentedToken: expectedToken,
        expectedToken,
      }),
    ).toBe(true);
  });

  it('still rejects a non-allowlisted IPv4-mapped IPv6 client IP', () => {
    expect(
      isPluggyRequestAuthentic({
        ip: '::ffff:203.0.113.9',
        allowedIps,
        presentedToken: expectedToken,
        expectedToken,
      }),
    ).toBe(false);
  });
});
