/**
 * Branded transactional emails for the Documenso signing lifecycle.
 *
 * Three template families:
 *
 *   1. signingInvitation - sent to a single signer when their turn to sign
 *      comes up. Used both for initial client invites AND cascading "your
 *      turn" emails when an earlier signer completes.
 *
 *   2. signingCompleted - sent to ALL signers (with the finalized signed
 *      PDF as an attachment) when the document reaches a fully signed state.
 *
 *   3. signingReminder - sent when a rep nudges manually OR when the
 *      rate-limited reminder service fires.
 *
 * All three use the per-port BrandingShell. The signing URL is expected
 * to already be embedded-format (e.g. /sign/<type>/<token>) - the caller
 * does the transformation from the raw Documenso URL.
 */

import { Button, Hr, Link, Text, render } from '@react-email/components';
import * as React from 'react';

import { brandingPrimaryColor, renderShell, safeUrl, type BrandingShell } from '@/lib/email/shell';
import { formatDate } from '@/lib/utils/format-date';

interface RenderOpts {
  subject?: string | null;
  branding?: BrandingShell | null;
}

// ─── 1. Invitation ───────────────────────────────────────────────────────────

interface InvitationData {
  recipientName: string;
  documentLabel: string;
  signerRole?: string | null;
  signingUrl: string;
  portName: string;
  senderName?: string | null;
  customMessage?: string | null;
}

function InvitationBody({ data, accent }: { data: InvitationData; accent: string }) {
  const greeting = `Dear ${data.recipientName},`;
  const role = data.signerRole ?? 'client';
  // §1.3 audit: role-specific copy stays order-agnostic. The original
  // copy assumed client→developer→approver order; ports can configure
  // any sequence, so generic phrasing is safer than naming the prior
  // signer.
  const leadCopy =
    role === 'client'
      ? `Your ${data.documentLabel} for ${data.portName} is ready for signing. Click the button below to review and sign - it should only take a couple of minutes.`
      : role === 'approver'
        ? `An ${data.documentLabel} is awaiting your approval. Please review and sign to finalise the document.`
        : role === 'developer'
          ? `An ${data.documentLabel} is awaiting your signature as developer. Please review and sign when ready.`
          : `An ${data.documentLabel} is awaiting your signature. Please review and sign when ready.`;

  return (
    <>
      <Text style={{ marginBottom: '14px', fontSize: '18px', fontWeight: 'bold', color: accent }}>
        {data.documentLabel} ready to sign
      </Text>
      <Text style={{ marginBottom: '14px', fontSize: '16px', lineHeight: '1.6' }}>{greeting}</Text>
      <Text style={{ marginBottom: '18px', fontSize: '16px', lineHeight: '1.6' }}>{leadCopy}</Text>
      {data.customMessage ? (
        <Text
          style={{
            margin: '20px 0',
            fontSize: '15px',
            lineHeight: '1.6',
            color: '#444',
            padding: '14px 18px',
            background: '#f8f9fb',
            borderLeft: `3px solid ${accent}`,
            borderRadius: '4px',
            whiteSpace: 'pre-wrap',
          }}
        >
          {data.customMessage}
        </Text>
      ) : null}
      <Text style={{ fontSize: '16px', marginTop: '8px' }}>
        With warm regards,
        <br />
        {data.senderName ? (
          <>
            {data.senderName}
            <br />
            <strong>The {data.portName} Team</strong>
          </>
        ) : (
          <strong>The {data.portName} Team</strong>
        )}
      </Text>
      <div style={{ textAlign: 'center', margin: '30px 0' }}>
        <Button
          href={safeUrl(data.signingUrl)}
          style={{
            display: 'inline-block',
            backgroundColor: accent,
            color: '#ffffff',
            textDecoration: 'none',
            padding: '14px 36px',
            borderRadius: '5px',
            fontWeight: 'bold',
            fontSize: '16px',
          }}
        >
          Review &amp; sign
        </Button>
      </div>
      <Hr style={{ border: 'none', borderTop: '1px solid #eee', margin: '24px 0 0' }} />
      <Text style={{ fontSize: '13px', color: '#666', lineHeight: '1.5', padding: '14px 0 0' }}>
        If the button doesn&apos;t work, paste this link into your browser:
        <br />
        <Link
          href={safeUrl(data.signingUrl)}
          style={{ color: accent, textDecoration: 'underline', wordBreak: 'break-all' }}
        >
          {data.signingUrl}
        </Link>
      </Text>
      <Text style={{ fontSize: '14px', color: '#666', lineHeight: '1.5', marginTop: '18px' }}>
        Signing happens directly inside our website - your data isn&apos;t sent to a third-party
        signing service.
      </Text>
    </>
  );
}

export async function signingInvitationEmail(
  data: InvitationData,
  overrides?: RenderOpts,
): Promise<{ subject: string; html: string; text: string }> {
  const accent = brandingPrimaryColor(overrides?.branding);
  const subject = overrides?.subject
    ? overrides.subject
        .replace(/\{\{documentLabel\}\}/g, data.documentLabel)
        .replace(/\{\{portName\}\}/g, data.portName)
        .replace(/\{\{recipientName\}\}/g, data.recipientName)
    : `${data.documentLabel} ready to sign - ${data.portName}`;

  const body = await render(<InvitationBody data={data} accent={accent} />, { pretty: false });

  const isClient = (data.signerRole ?? 'client') === 'client';
  const leadText = isClient
    ? `Your ${data.documentLabel} for ${data.portName} is ready for signing.`
    : data.signerRole === 'approver'
      ? `An ${data.documentLabel} is awaiting your approval.`
      : `An ${data.documentLabel} is awaiting your signature.`;
  const text = `Dear ${data.recipientName},\n\n${leadText}\n\n${data.customMessage ? data.customMessage + '\n\n' : ''}Sign here: ${data.signingUrl}\n\nWith warm regards,\n${data.senderName ?? `The ${data.portName} Team`}`;

  return {
    subject,
    html: renderShell({ title: subject, body, branding: overrides?.branding }),
    text,
  };
}

// ─── 2. Completed ─────────────────────────────────────────────────────────────

interface CompletedData {
  recipientName: string;
  documentLabel: string;
  clientName: string;
  portName: string;
  completedAt: Date;
}

function CompletedBody({
  data,
  accent,
  completedDateStr,
}: {
  data: CompletedData;
  accent: string;
  completedDateStr: string;
}) {
  const greeting = `Dear ${data.recipientName},`;
  return (
    <>
      <Text style={{ marginBottom: '14px', fontSize: '18px', fontWeight: 'bold', color: accent }}>
        {data.documentLabel} signed by all parties
      </Text>
      <Text style={{ marginBottom: '14px', fontSize: '16px', lineHeight: '1.6' }}>{greeting}</Text>
      <Text style={{ marginBottom: '18px', fontSize: '16px', lineHeight: '1.6' }}>
        The {data.documentLabel} for <strong>{data.clientName}</strong> has been signed by every
        party as of {completedDateStr}.
      </Text>
      <Text style={{ marginBottom: '18px', fontSize: '16px', lineHeight: '1.6' }}>
        The fully signed PDF is attached to this email for your records. A copy has also been stored
        in the {data.portName} CRM.
      </Text>
      <Text style={{ fontSize: '16px', marginTop: '30px' }}>
        With warm regards,
        <br />
        <strong>The {data.portName} Team</strong>
      </Text>
    </>
  );
}

export async function signingCompletedEmail(
  data: CompletedData,
  overrides?: RenderOpts,
): Promise<{ subject: string; html: string; text: string }> {
  const accent = brandingPrimaryColor(overrides?.branding);
  const subject = overrides?.subject
    ? overrides.subject
        .replace(/\{\{documentLabel\}\}/g, data.documentLabel)
        .replace(/\{\{clientName\}\}/g, data.clientName)
        .replace(/\{\{portName\}\}/g, data.portName)
    : `${data.documentLabel} fully signed - ${data.clientName}`;
  const completedDateStr = formatDate(data.completedAt, 'datetime.medium');

  const body = await render(
    <CompletedBody data={data} accent={accent} completedDateStr={completedDateStr} />,
    { pretty: false },
  );

  const text = `Dear ${data.recipientName},\n\nThe ${data.documentLabel} for ${data.clientName} has been signed by all parties on ${completedDateStr}. The signed PDF is attached for your records.\n\nWith warm regards,\nThe ${data.portName} Team`;

  return {
    subject,
    html: renderShell({ title: subject, body, branding: overrides?.branding }),
    text,
  };
}

// ─── 3. Reminder ──────────────────────────────────────────────────────────────

interface ReminderData {
  recipientName: string;
  documentLabel: string;
  signingUrl: string;
  portName: string;
  invitedAgo: string;
  customMessage?: string | null;
}

function ReminderBody({ data, accent }: { data: ReminderData; accent: string }) {
  const greeting = `Dear ${data.recipientName},`;
  return (
    <>
      <Text style={{ marginBottom: '14px', fontSize: '18px', fontWeight: 'bold', color: accent }}>
        Just a quick reminder
      </Text>
      <Text style={{ marginBottom: '14px', fontSize: '16px', lineHeight: '1.6' }}>{greeting}</Text>
      <Text style={{ marginBottom: '18px', fontSize: '16px', lineHeight: '1.6' }}>
        We sent you a {data.documentLabel} {data.invitedAgo} that&apos;s still awaiting your
        signature. If you&apos;ve already signed, please disregard this message - it can take a few
        minutes for our system to catch up.
      </Text>
      {data.customMessage ? (
        <Text
          style={{
            margin: '20px 0',
            fontSize: '15px',
            lineHeight: '1.6',
            color: '#444',
            padding: '14px 18px',
            background: '#f8f9fb',
            borderLeft: `3px solid ${accent}`,
            borderRadius: '4px',
            whiteSpace: 'pre-wrap',
          }}
        >
          {data.customMessage}
        </Text>
      ) : null}
      <Text style={{ fontSize: '16px', marginTop: '8px' }}>
        With warm regards,
        <br />
        <strong>The {data.portName} Team</strong>
      </Text>
      <div style={{ textAlign: 'center', margin: '30px 0' }}>
        <Button
          href={safeUrl(data.signingUrl)}
          style={{
            display: 'inline-block',
            backgroundColor: accent,
            color: '#ffffff',
            textDecoration: 'none',
            padding: '14px 36px',
            borderRadius: '5px',
            fontWeight: 'bold',
            fontSize: '16px',
          }}
        >
          Sign now
        </Button>
      </div>
      <Hr style={{ border: 'none', borderTop: '1px solid #eee', margin: '24px 0 0' }} />
      <Text style={{ fontSize: '13px', color: '#666', lineHeight: '1.5', padding: '14px 0 0' }}>
        Direct link:{' '}
        <Link
          href={safeUrl(data.signingUrl)}
          style={{ color: accent, textDecoration: 'underline', wordBreak: 'break-all' }}
        >
          {data.signingUrl}
        </Link>
      </Text>
    </>
  );
}

export async function signingReminderEmail(
  data: ReminderData,
  overrides?: RenderOpts,
): Promise<{ subject: string; html: string; text: string }> {
  const accent = brandingPrimaryColor(overrides?.branding);
  const subject = overrides?.subject
    ? overrides.subject
        .replace(/\{\{documentLabel\}\}/g, data.documentLabel)
        .replace(/\{\{portName\}\}/g, data.portName)
    : `Friendly reminder: ${data.documentLabel} still awaiting your signature - ${data.portName}`;

  const body = await render(<ReminderBody data={data} accent={accent} />, { pretty: false });

  const text = `Dear ${data.recipientName},\n\nWe sent you a ${data.documentLabel} ${data.invitedAgo} that's still awaiting your signature. ${data.customMessage ? '\n\n' + data.customMessage + '\n\n' : ''}\n\nSign here: ${data.signingUrl}\n\nWith warm regards,\nThe ${data.portName} Team`;

  return {
    subject,
    html: renderShell({ title: subject, body, branding: overrides?.branding }),
    text,
  };
}

// ─── 4. Cancelled ─────────────────────────────────────────────────────────────

interface CancelledData {
  recipientName: string;
  documentLabel: string;
  portName: string;
  /** Optional rep-authored reason. When null, the body explains the
   *  cancellation without speculation; when set, the reason renders in
   *  the same callout style as the invitation `customMessage`. */
  reason?: string | null;
}

function CancelledBody({ data, accent }: { data: CancelledData; accent: string }) {
  const greeting = `Dear ${data.recipientName},`;
  return (
    <>
      <Text style={{ marginBottom: '14px', fontSize: '18px', fontWeight: 'bold', color: accent }}>
        {data.documentLabel} cancelled
      </Text>
      <Text style={{ marginBottom: '14px', fontSize: '16px', lineHeight: '1.6' }}>{greeting}</Text>
      <Text style={{ marginBottom: '18px', fontSize: '16px', lineHeight: '1.6' }}>
        The {data.documentLabel} you were signing for {data.portName} has been cancelled. No further
        action is required from you - any signing link previously sent is no longer valid.
      </Text>
      {data.reason ? (
        <Text
          style={{
            margin: '20px 0',
            fontSize: '15px',
            lineHeight: '1.6',
            color: '#444',
            padding: '14px 18px',
            background: '#f8f9fb',
            borderLeft: `3px solid ${accent}`,
            borderRadius: '4px',
            whiteSpace: 'pre-wrap',
          }}
        >
          {data.reason}
        </Text>
      ) : null}
      <Text style={{ marginBottom: '18px', fontSize: '16px', lineHeight: '1.6' }}>
        If you have any questions, please reach out to your representative at {data.portName}.
      </Text>
      <Hr style={{ border: 'none', borderTop: '1px solid #eee', margin: '24px 0 0' }} />
      <Text style={{ fontSize: '16px', marginTop: '24px' }}>
        With warm regards,
        <br />
        <strong>The {data.portName} Team</strong>
      </Text>
    </>
  );
}

export async function signingCancelledEmail(
  data: CancelledData,
  overrides?: RenderOpts,
): Promise<{ subject: string; html: string; text: string }> {
  const accent = brandingPrimaryColor(overrides?.branding);
  const subject = overrides?.subject
    ? overrides.subject
        .replace(/\{\{documentLabel\}\}/g, data.documentLabel)
        .replace(/\{\{portName\}\}/g, data.portName)
    : `${data.documentLabel} cancelled - ${data.portName}`;
  const body = await render(<CancelledBody data={data} accent={accent} />, { pretty: false });
  const text = `Dear ${data.recipientName},\n\nThe ${data.documentLabel} you were signing for ${data.portName} has been cancelled. No further action is required.${data.reason ? '\n\nReason: ' + data.reason : ''}\n\nWith warm regards,\nThe ${data.portName} Team`;
  return {
    subject,
    html: renderShell({ title: subject, body, branding: overrides?.branding }),
    text,
  };
}
