import { and, eq } from 'drizzle-orm'; import { db } from '@/lib/db'; import { systemSettings } from '@/lib/db/schema/system'; import type { EoiContext } from '@/lib/services/eoi-context'; export interface DocumensoTemplatePayload { title: string; externalId: string; meta: { message: string; subject: string; redirectUrl: string; distributionMethod: 'NONE' | 'EMAIL'; }; formValues: { Name: string; Email: string; Address: string; 'Yacht Name': string; Length: string; Width: string; Draft: string; 'Berth Number': string; Lease_10: boolean; Purchase: boolean; }; recipients: Array<{ id: number; name: string; email: string; role: 'SIGNER' | 'APPROVER'; signingOrder: number; }>; } export interface DocumensoPayloadOptions { /** `interestId` used to build `externalId` and Documenso referencing. */ interestId: string; /** Documenso recipient IDs — come from env vars. */ clientRecipientId: number; developerRecipientId: number; approvalRecipientId: number; /** Hardcoded developer + approver names/emails (legacy). */ developerName?: string; developerEmail?: string; approverName?: string; approverEmail?: string; /** Redirect URL after signing. Defaults to the app URL. */ redirectUrl?: string; } const DEFAULT_DEVELOPER_NAME = 'David Mizrahi'; const DEFAULT_DEVELOPER_EMAIL = 'dm@portnimara.com'; const DEFAULT_APPROVER_NAME = 'Abbie May'; const DEFAULT_APPROVER_EMAIL = 'sales@portnimara.com'; const DEFAULT_REDIRECT_URL = 'https://portnimara.com'; export interface EoiSignerConfig { developer: { name: string; email: string }; approver: { name: string; email: string }; } const DEFAULT_EOI_SIGNERS: EoiSignerConfig = { developer: { name: DEFAULT_DEVELOPER_NAME, email: DEFAULT_DEVELOPER_EMAIL }, approver: { name: DEFAULT_APPROVER_NAME, email: DEFAULT_APPROVER_EMAIL }, }; function isSignerEntry(v: unknown): v is { name: string; email: string } { return ( !!v && typeof v === 'object' && typeof (v as Record).name === 'string' && typeof (v as Record).email === 'string' && !!(v as Record).name && !!(v as Record).email ); } /** Read the per-port `eoi_signers` setting, fall back to legacy hardcoded * defaults if missing or malformed. The fallback exists to keep older * ports working until an admin saves the setting; once saved, the DB row * always wins. */ export async function getPortEoiSigners(portId: string): Promise { const row = await db.query.systemSettings.findFirst({ where: and(eq(systemSettings.key, 'eoi_signers'), eq(systemSettings.portId, portId)), }); const value = row?.value as Record | undefined; if (value && isSignerEntry(value.developer) && isSignerEntry(value.approver)) { return { developer: value.developer, approver: value.approver, }; } return DEFAULT_EOI_SIGNERS; } function formatAddress(address: EoiContext['client']['address']): string { if (!address) return ''; return [address.street, address.city, address.country].filter(Boolean).join(', '); } function buildMessage(context: EoiContext): string { const greeting = `Dear ${context.client.fullName},`; const body = `Thank you for your interest in a berth at ${context.port.name}. Please click the link above to sign your LOI.`; const onBehalf = context.owner.type === 'company' && context.company ? `\n\nOn behalf of ${context.company.legalName ?? context.company.name} (representing the yacht's owner).` : ''; const footer = `\n\nBest Regards,\n${context.port.name} Team`; return `${greeting}\n\n${body}${onBehalf}${footer}`; } export function buildDocumensoPayload( context: EoiContext, options: DocumensoPayloadOptions, ): DocumensoTemplatePayload { return { title: `${context.client.fullName}-EOI-NDA`, externalId: `loi-${options.interestId}`, meta: { message: buildMessage(context), subject: 'Your LOI is ready to be signed', redirectUrl: options.redirectUrl ?? DEFAULT_REDIRECT_URL, distributionMethod: 'NONE', }, formValues: { Name: context.client.fullName, Email: context.client.primaryEmail ?? '', Address: formatAddress(context.client.address), // Yacht + berth are optional EOI fields; when not linked, render as // empty strings so the corresponding template inputs stay blank. 'Yacht Name': context.yacht?.name ?? '', Length: context.yacht?.lengthFt ?? '', Width: context.yacht?.widthFt ?? '', Draft: context.yacht?.draftFt ?? '', 'Berth Number': context.berth?.mooringNumber ?? '', Lease_10: false, Purchase: true, }, recipients: [ { id: options.clientRecipientId, name: context.client.fullName, email: context.client.primaryEmail ?? '', role: 'SIGNER', signingOrder: 1, }, { id: options.developerRecipientId, name: options.developerName ?? DEFAULT_DEVELOPER_NAME, email: options.developerEmail ?? DEFAULT_DEVELOPER_EMAIL, role: 'SIGNER', signingOrder: 2, }, { id: options.approvalRecipientId, name: options.approverName ?? DEFAULT_APPROVER_NAME, email: options.approverEmail ?? DEFAULT_APPROVER_EMAIL, role: 'APPROVER', signingOrder: 3, }, ], }; }