import { beforeEach, describe, expect, it, vi } from 'vitest';

// Documenso 2.13's v1-compat `GET /api/v1/documents/{id}/download` returns
// JSON `{ downloadUrl }` (a presigned S3 URL), NOT raw PDF bytes. The CRM was
// saving that ~500-byte JSON as the "signed PDF" → corrupt file emailed to every
// signer + filed in the CRM. These tests pin the two-step follow behaviour.

vi.mock('@/lib/fetch-with-timeout', () => ({
  fetchWithTimeout: vi.fn(),
  FetchTimeoutError: class FetchTimeoutError extends Error {
    timeoutMs = 0;
  },
}));
vi.mock('@/lib/services/port-config', () => ({
  getPortDocumensoConfig: vi.fn().mockResolvedValue({
    apiUrl: 'https://sig.example.com',
    apiKey: 'k',
    apiVersion: 'v1',
  }),
}));
vi.mock('@/lib/logger', () => ({
  logger: { error: vi.fn(), warn: vi.fn(), info: vi.fn(), debug: vi.fn() },
}));

import { downloadSignedPdf } from '@/lib/services/documenso-client';
import { fetchWithTimeout } from '@/lib/fetch-with-timeout';

const mockFetch = vi.mocked(fetchWithTimeout);

function jsonRes(obj: unknown) {
  const bytes = Buffer.from(JSON.stringify(obj));
  return {
    ok: true,
    status: 200,
    arrayBuffer: async () => bytes,
    text: async () => JSON.stringify(obj),
    headers: { get: () => 'application/json' },
  } as unknown as Response;
}
function pdfRes(text: string) {
  const bytes = Buffer.from(text);
  return {
    ok: true,
    status: 200,
    arrayBuffer: async () => bytes,
    headers: { get: () => 'application/pdf' },
  } as unknown as Response;
}

describe('downloadSignedPdf (v1) — Documenso 2.13 JSON downloadUrl', () => {
  beforeEach(() => mockFetch.mockReset());

  it('follows the JSON { downloadUrl } and returns the real signed PDF bytes', async () => {
    mockFetch
      .mockResolvedValueOnce(jsonRes({ downloadUrl: 'https://s3.example/signed.pdf?sig=1' }))
      .mockResolvedValueOnce(pdfRes('%PDF-1.7\nreal signed content'));

    const buf = await downloadSignedPdf('117', 'port-1');

    expect(buf.subarray(0, 5).toString('latin1')).toBe('%PDF-');
    expect(buf.toString()).toContain('real signed content');
    expect(mockFetch).toHaveBeenCalledTimes(2);
    expect(mockFetch.mock.calls[1]![0]).toBe('https://s3.example/signed.pdf?sig=1');
  });

  it('returns raw PDF directly when the endpoint already serves PDF bytes (older v1)', async () => {
    mockFetch.mockResolvedValueOnce(pdfRes('%PDF-1.7 direct bytes'));

    const buf = await downloadSignedPdf('118', 'port-1');

    expect(buf.toString()).toContain('direct bytes');
    expect(mockFetch).toHaveBeenCalledTimes(1);
  });

  it('throws when the body is neither a PDF nor a downloadUrl JSON', async () => {
    mockFetch.mockResolvedValueOnce(jsonRes({ nope: true }));
    await expect(downloadSignedPdf('119', 'port-1')).rejects.toThrow();
  });
});
