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

// Boundaries the sender depends on — mock the I/O edges, exercise the real
// wiring (recipient resolution → template → per-recipient send).
vi.mock('@/lib/email', () => ({ sendEmail: vi.fn().mockResolvedValue(undefined) }));
vi.mock('@/lib/email/branding-resolver', () => ({
  getBrandingShell: vi.fn().mockResolvedValue(null),
}));
vi.mock('@/lib/services/notification-recipients', () => ({
  resolveNotificationRecipients: vi.fn(),
}));

import { sendEmail } from '@/lib/email';
import { resolveNotificationRecipients } from '@/lib/services/notification-recipients';
import { sendSigningStatusNotification } from '@/lib/services/document-signing-emails.service';

const mockSendEmail = vi.mocked(sendEmail);
const mockResolve = vi.mocked(resolveNotificationRecipients);

const baseArgs = {
  portId: 'port-1',
  portName: 'Port Nimara',
  event: 'signed' as const,
  documentLabel: 'Expression of Interest',
  clientName: 'Jane Doe',
  crmUrl: 'https://crm.portnimara.com/port-nimara/documents/abc',
  signerName: 'Jane Doe',
  signerRole: 'client' as const,
  signedCount: 1,
  totalCount: 3,
};

describe('sendSigningStatusNotification', () => {
  beforeEach(() => {
    mockSendEmail.mockClear();
    mockResolve.mockReset();
  });

  it('emails every configured recipient when a signer signs', async () => {
    mockResolve.mockResolvedValue(['admin@portnimara.com', 'sales@portnimara.com']);

    await sendSigningStatusNotification(baseArgs);

    // Resolves from the signing list, falling back to the reply-to address.
    expect(mockResolve).toHaveBeenCalledWith(
      'port-1',
      'signing_notification_recipients',
      'email_reply_to',
    );
    expect(mockSendEmail).toHaveBeenCalledTimes(2);
    const recipients = mockSendEmail.mock.calls.map((c) => c[0]);
    expect(recipients).toContain('admin@portnimara.com');
    expect(recipients).toContain('sales@portnimara.com');
    // Subject reflects who signed.
    const subject = mockSendEmail.mock.calls[0]?.[1] as string;
    expect(subject).toContain('Jane Doe');
    // portId threaded through so per-port From + redirect apply.
    expect(mockSendEmail.mock.calls[0]?.[5]).toBe('port-1');
  });

  it('sends nothing when no recipients are configured or resolvable', async () => {
    mockResolve.mockResolvedValue([]);

    await sendSigningStatusNotification(baseArgs);

    expect(mockSendEmail).not.toHaveBeenCalled();
  });

  it('uses the completion subject for the completed event', async () => {
    mockResolve.mockResolvedValue(['sales@portnimara.com']);

    await sendSigningStatusNotification({
      ...baseArgs,
      event: 'completed',
      signerName: null,
    });

    const subject = mockSendEmail.mock.calls[0]?.[1] as string;
    expect(subject.toLowerCase()).toContain('fully signed');
    expect(subject).toContain('Jane Doe');
  });
});
