/**
 * Tests for the Documenso webhook receiver route at
 * `src/app/api/webhooks/documenso/route.ts`.
 *
 * The receiver was previously only covered indirectly: the unit test
 * `webhook-event-map.test.ts` validates the static event-name map, and
 * `documents-expired-webhook.test.ts` calls handlers directly. Neither
 * exercised the route's auth, dedup, dispatch loop, or 200-on-failure
 * envelope. This file fills that gap.
 *
 * Refs: docs/audit-comprehensive-2026-05-05.md HIGH §19 (auditor-J Issue 2).
 */
import { describe, it, expect } from 'vitest';
import { eq } from 'drizzle-orm';
import { NextRequest } from 'next/server';

import { POST as documensoWebhook } from '@/app/api/webhooks/documenso/route';
import { db } from '@/lib/db';
import { documents, documentEvents } from '@/lib/db/schema/documents';
import { env } from '@/lib/env';
import { makeClient, makePort } from '../helpers/factories';

function buildRequest(body: Record<string, unknown>, secret: string): NextRequest {
  return new NextRequest('http://localhost:3000/api/webhooks/documenso', {
    method: 'POST',
    headers: {
      'content-type': 'application/json',
      'x-documenso-secret': secret,
    },
    body: JSON.stringify(body),
  });
}

describe('Documenso webhook route', () => {
  it('returns 200 with ok:false when the secret header is missing or wrong', async () => {
    const req = buildRequest(
      { event: 'DOCUMENT_SIGNED', payload: { id: 'abc', recipients: [] } },
      'wrong-secret',
    );
    const res = await documensoWebhook(req);
    expect(res.status).toBe(200);
    const body = await res.json();
    expect(body).toMatchObject({ ok: false });
  });

  it('with a valid secret + DOCUMENT_SIGNED writes a documentEvents row', async () => {
    const port = await makePort();
    const client = await makeClient({ portId: port.id });

    const documensoId = `docu-test-${Date.now()}`;
    const [doc] = await db
      .insert(documents)
      .values({
        portId: port.id,
        clientId: client.id,
        documentType: 'eoi',
        title: 'Webhook test EOI',
        status: 'sent',
        documensoId,
        createdBy: 'seed',
      })
      .returning();

    const req = buildRequest(
      {
        event: 'DOCUMENT_SIGNED',
        payload: {
          id: documensoId,
          recipients: [{ email: 'signer@test.invalid', signingStatus: 'SIGNED' }],
        },
      },
      env.DOCUMENSO_WEBHOOK_SECRET,
    );
    const res = await documensoWebhook(req);
    expect(res.status).toBe(200);

    const events = await db
      .select()
      .from(documentEvents)
      .where(eq(documentEvents.documentId, doc!.id));
    expect(events.length).toBeGreaterThanOrEqual(1);
  });

  it('replays of the same body are no-ops (signatureHash dedup)', async () => {
    const port = await makePort();
    const client = await makeClient({ portId: port.id });

    const documensoId = `docu-dedup-${Date.now()}`;
    const [doc] = await db
      .insert(documents)
      .values({
        portId: port.id,
        clientId: client.id,
        documentType: 'eoi',
        title: 'Dedup test EOI',
        status: 'sent',
        documensoId,
        createdBy: 'seed',
      })
      .returning();

    const body = {
      event: 'DOCUMENT_OPENED',
      payload: {
        id: documensoId,
        recipients: [{ email: 'opener@test.invalid', readStatus: 'OPENED' }],
      },
    };

    await documensoWebhook(buildRequest(body, env.DOCUMENSO_WEBHOOK_SECRET));
    await documensoWebhook(buildRequest(body, env.DOCUMENSO_WEBHOOK_SECRET));

    const events = await db
      .select()
      .from(documentEvents)
      .where(eq(documentEvents.documentId, doc!.id));
    // The route's `handleDocumentOpened` writes an event with type
    // `'viewed'`. One row from the first call; the second should have
    // been refused by the signatureHash dedup guard.
    const viewedEvents = events.filter((e) => e.eventType === 'viewed');
    expect(viewedEvents.length).toBe(1);
  });
});
