import { describe, expect, it } from 'vitest';
import { createHmac } from 'node:crypto';
import { StripePaymentProvider } from '../infrastructure/stripe-payment-provider.js';
import { InvalidWebhookSignatureError } from '../domain/errors.js';

const SECRET = 'whsec_test';

function sign(rawBody: string, timestamp = Math.floor(Date.now() / 1000)): string {
  const expected = createHmac('sha256', SECRET).update(`${timestamp}.${rawBody}`).digest('hex');
  return `t=${timestamp},v1=${expected}`;
}

describe('StripePaymentProvider', () => {
  it('verifies a signed payload', () => {
    const provider = new StripePaymentProvider(SECRET);
    const body = JSON.stringify({
      id: 'evt_1',
      type: 'payment_intent.succeeded',
      data: {
        object: {
          id: 'pi_1',
          metadata: { order_id: '11111111-1111-1111-1111-111111111111', amount: 1234 },
        },
      },
    });
    const event = provider.verifyWebhook(body, sign(body));
    expect(event.type).toBe('PaymentSucceeded');
    expect(event.status).toBe('succeeded');
    expect(event.amountCents).toBe(1234);
    expect(event.providerPaymentId).toBe('pi_1');
  });

  it('rejects an invalid signature with non-2xx (mapped to 400 by API)', () => {
    const provider = new StripePaymentProvider(SECRET);
    expect(() => provider.verifyWebhook('{}', 't=1,v1=deadbeef')).toThrow(
      InvalidWebhookSignatureError,
    );
  });

  it('rejects a missing signature', () => {
    const provider = new StripePaymentProvider(SECRET);
    expect(() => provider.verifyWebhook('{}', undefined)).toThrow(InvalidWebhookSignatureError);
  });

  it('rejects an expired timestamp', () => {
    const provider = new StripePaymentProvider(SECRET);
    const body = '{}';
    const oldTimestamp = Math.floor(Date.now() / 1000) - 3600;
    expect(() => provider.verifyWebhook(body, sign(body, oldTimestamp))).toThrow(
      InvalidWebhookSignatureError,
    );
  });

  it('rejects an unsupported event type', () => {
    const provider = new StripePaymentProvider(SECRET);
    const body = JSON.stringify({ id: 'evt_2', type: 'something.else', data: { object: {} } });
    expect(() => provider.verifyWebhook(body, sign(body))).toThrow(InvalidWebhookSignatureError);
  });
});
