/**
 * Small helpers shared between the document-signing flows and the
 * Documenso webhook handlers. Kept in their own file so the two
 * heavyweight callers (`documents.service.ts` + the webhook handler
 * routes) don't have to depend on each other for a 30-line utility.
 */

import type { DocumentLabel } from '@/lib/services/document-signing-emails.service';
import type { DocumentSigner } from '@/lib/db/schema/documents';

/**
 * Pull the per-recipient signing token out of a Documenso signing URL.
 * Both v1.13 and v2 emit URLs of the form
 *   `https://signatures.example.com/sign/<token>`
 * so the token is the last non-empty path segment. Returns null when
 * the URL is empty / unparseable / doesn't carry a token-shaped tail.
 *
 * Used at document-send time to populate `document_signers.signing_token`
 * so subsequent webhook deliveries can match recipients by token
 * (more robust than email match when one address serves multiple roles).
 */
export function extractSigningToken(url: string | null | undefined): string | null {
  if (!url) return null;
  let parsed: URL;
  try {
    parsed = new URL(url);
  } catch {
    return null;
  }
  const segments = parsed.pathname.split('/').filter(Boolean);
  const last = segments[segments.length - 1];
  if (!last) return null;
  // A token must be at least 8 chars and contain only URL-safe chars -
  // discriminates real tokens from generic words like "sign" or "embed"
  // that some Documenso 2.x deployments append.
  if (last.length < 8) return null;
  if (!/^[A-Za-z0-9_-]+$/.test(last)) return null;
  return last;
}

/** Map of internal documentType to the customer-facing label used in
 *  email subjects + body copy. Duplicated in send-invitation/route.ts
 *  but consolidated here so the webhook cascade picks up the same
 *  label without re-defining the map. */
export const DOC_TYPE_LABEL: Record<string, DocumentLabel> = {
  eoi: 'Expression of Interest',
  contract: 'Sales Contract',
  reservation_agreement: 'Reservation Agreement',
};

/** Pick the next pending signer in signing order. Returns null when
 *  every signer in the list has signed (or declined). */
export function nextPendingSigner<T extends Pick<DocumentSigner, 'status' | 'signingOrder'>>(
  signers: T[],
): T | null {
  // signers list is assumed pre-sorted asc by signingOrder; we
  // defensively pick the lowest-order pending row regardless.
  const pending = signers.filter((s) => s.status === 'pending');
  if (pending.length === 0) return null;
  return pending.reduce((lo, s) => (s.signingOrder < lo.signingOrder ? s : lo));
}
