/**
 * Tests for /api/webhooks/[...path] — external integration proxy.
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import type { NextRequest } from 'next/server';

const mockFetch = vi.fn();
vi.stubGlobal('fetch', mockFetch);

import { POST } from '@/app/api/webhooks/[...path]/route';

function mockNextRequest(body?: string, headers?: Record<string, string>): NextRequest {
  const headerMap = new Map(Object.entries(headers || {}));
  return {
    method: 'POST',
    headers: {
      get: (key: string) => headerMap.get(key.toLowerCase()) || headerMap.get(key) || null,
    },
    nextUrl: {
      searchParams: new URLSearchParams('source=gitea'),
    },
    text: async () => body || '',
  } as unknown as NextRequest;
}

describe('webhook proxy', () => {
  const originalEnv = { ...process.env };

  beforeEach(() => {
    vi.clearAllMocks();
    process.env.PLATFORM_API_URL = 'http://localhost:4003';
  });

  afterEach(() => {
    process.env = { ...originalEnv };
  });

  it('proxies external webhook payloads and signature headers', async () => {
    mockFetch.mockResolvedValue({
      status: 202,
      text: async () => JSON.stringify({ accepted: true }),
    });
    const body = JSON.stringify({ action: 'closed', pull_request: { number: 12 } });
    const req = mockNextRequest(body, {
      'x-hub-signature-256': 'sha256=test',
      'x-gitea-event': 'pull_request',
      'x-product-id': 'tracker',
    });

    const res = await POST(req, { params: Promise.resolve({ path: ['gitea'] }) });

    expect(res.status).toBe(202);
    expect(mockFetch).toHaveBeenCalledWith(
      expect.stringContaining('/api/webhooks/gitea?source=gitea'),
      expect.objectContaining({
        method: 'POST',
        body,
        headers: expect.objectContaining({
          'x-hub-signature-256': 'sha256=test',
          'x-gitea-event': 'pull_request',
          'x-product-id': 'tracker',
        }),
      })
    );
  });

  it('returns 502 when webhook ingestion is unavailable', async () => {
    mockFetch.mockRejectedValue(new Error('ECONNREFUSED'));

    const res = await POST(mockNextRequest('{}'), {
      params: Promise.resolve({ path: ['github'] }),
    });

    expect(res.status).toBe(502);
    await expect(res.json()).resolves.toEqual({ error: 'Webhook ingestion unavailable' });
  });
});
