import {
  signWebhookPayload,
  verifyWebhookSignature,
} from './webhook-signature.util';

describe('webhook-signature.util', () => {
  const secret = 'super-secret';
  const ts = '1700000000';
  const body = '{"orderId":42}';

  describe('verifyWebhookSignature', () => {
    it('returns true for a valid signature', () => {
      const sig = signWebhookPayload(secret, ts, body);
      expect(verifyWebhookSignature(secret, ts, body, sig)).toBe(true);
    });

    it('returns false when secret is wrong', () => {
      const sig = signWebhookPayload(secret, ts, body);
      expect(verifyWebhookSignature('different', ts, body, sig)).toBe(false);
    });

    it('returns false when body is tampered', () => {
      const sig = signWebhookPayload(secret, ts, body);
      expect(verifyWebhookSignature(secret, ts, '{"orderId":99}', sig)).toBe(
        false,
      );
    });

    it('returns false when timestamp differs', () => {
      const sig = signWebhookPayload(secret, ts, body);
      expect(verifyWebhookSignature(secret, '1700000099', body, sig)).toBe(
        false,
      );
    });

    it('returns false on missing signature header', () => {
      expect(verifyWebhookSignature(secret, ts, body, undefined)).toBe(false);
    });

    it('returns false on missing secret', () => {
      const sig = signWebhookPayload(secret, ts, body);
      expect(verifyWebhookSignature('', ts, body, sig)).toBe(false);
    });

    it('returns false (no throw) on length-mismatched signature', () => {
      expect(() =>
        verifyWebhookSignature(secret, ts, body, 'sha256=short'),
      ).not.toThrow();
      expect(verifyWebhookSignature(secret, ts, body, 'sha256=short')).toBe(
        false,
      );
    });

    it('accepts Buffer body input', () => {
      const buf = Buffer.from(body);
      const sig = signWebhookPayload(secret, ts, buf);
      expect(verifyWebhookSignature(secret, ts, buf, sig)).toBe(true);
    });

    it('produces different signatures for different timestamps (replay protection)', () => {
      const sig1 = signWebhookPayload(secret, '1700000000', body);
      const sig2 = signWebhookPayload(secret, '1700000001', body);
      expect(sig1).not.toBe(sig2);
    });
  });

  describe('signWebhookPayload', () => {
    it('produces a sha256= prefixed hex digest', () => {
      const sig = signWebhookPayload(secret, ts, body);
      expect(sig).toMatch(/^sha256=[a-f0-9]{64}$/);
    });

    it('is deterministic for same inputs', () => {
      expect(signWebhookPayload(secret, ts, body)).toBe(
        signWebhookPayload(secret, ts, body),
      );
    });
  });
});
