import { describe, it, expect, afterEach } from 'vitest';
import { createServer, type Server } from 'http';
import { computeWebhookSignature } from '@dbis/integration-foundation';
import { createWebhookServer } from './adapters/webhookServer';

describe('webhookServer', () => {
  let server: Server | undefined;
  const port = 18765;
  const secret = 'test-webhook-secret-dummy';

  afterEach(() => {
    server?.close();
    server = undefined;
  });

  it('rejects invalid HMAC signature', async () => {
    const messages: unknown[] = [];
    server = createWebhookServer({
      port,
      path: '/webhook',
      webhookSecret: secret,
      onMessage: async (msg) => {
        messages.push(msg);
      },
    });

    await new Promise((r) => setTimeout(r, 100));

    const res = await fetch(`http://127.0.0.1:${port}/webhook`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'x-hybx-signature': 'bad' },
      body: '{"test":true}',
    });
    expect(res.status).toBe(401);
    expect(messages.length).toBe(0);
  });

  it('accepts valid HMAC signature and sets correlation headers', async () => {
    const messages: unknown[] = [];
    server = createWebhookServer({
      port,
      path: '/webhook',
      webhookSecret: secret,
      onMessage: async (msg) => {
        messages.push(msg);
      },
    });

    await new Promise((r) => setTimeout(r, 100));

    const body = '{"eventType":"payment.status"}';
    const sig = computeWebhookSignature(secret, body);
    const res = await fetch(`http://127.0.0.1:${port}/webhook`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-hybx-signature': sig,
        'x-idempotency-key': 'test-key-001',
      },
      body,
    });
    expect(res.status).toBe(202);
    expect(res.headers.get('x-correlation-id')).toBeTruthy();
    expect(messages.length).toBe(1);
  });

  it('returns 409 on duplicate idempotency key', async () => {
    server = createWebhookServer({
      port: port + 1,
      path: '/webhook',
      webhookSecret: secret,
      onMessage: async () => {},
    });

    await new Promise((r) => setTimeout(r, 100));

    const body = '{"eventType":"dup"}';
    const sig = computeWebhookSignature(secret, body);
    const headers = {
      'Content-Type': 'application/json',
      'x-hybx-signature': sig,
      'x-idempotency-key': 'dup-key-001',
    };
    const url = `http://127.0.0.1:${port + 1}/webhook`;
    const first = await fetch(url, { method: 'POST', headers, body });
    const second = await fetch(url, { method: 'POST', headers, body });
    expect(first.status).toBe(202);
    expect(second.status).toBe(409);
  });
});
