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

import { brandingPrimaryColor, renderShell, safeUrl, type BrandingShell } from '@/lib/email/shell';

interface ActivationData {
  portName: string;
  link: string;
  ttlHours: number;
  recipientName?: string;
}

interface ResetData {
  portName: string;
  link: string;
  ttlMinutes: number;
  recipientName?: string;
}

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

// ─── React-email body components ──────────────────────────────────────────────

// react-email's `render()` auto-escapes string interpolation, so we don't
// need our hand-rolled escapeHtml() on these bodies. Inline styles use
// camelCase per CSSProperties — react-email serialises them to
// email-client-safe inline `style="..."` attributes on output.

function ActivationBody({
  portName,
  link,
  ttlHours,
  recipientName,
  accent,
}: ActivationData & { accent: string }) {
  const greeting = recipientName ? `Dear ${recipientName},` : 'Welcome aboard,';

  return (
    <>
      <Text
        style={{
          marginBottom: '10px',
          fontSize: '18px',
          fontWeight: 'bold',
          color: accent,
        }}
      >
        Welcome to {portName}
      </Text>
      <Text style={{ marginBottom: '10px', fontSize: '16px', lineHeight: '1.5' }}>{greeting}</Text>
      <Text style={{ marginBottom: '20px', fontSize: '16px', lineHeight: '1.5' }}>
        It&apos;s our pleasure to invite you to the {portName} client portal — your private space to
        review your berth, manage signed documents, and stay in touch with your sales liaison. The
        button below will let you set a password and activate your account at your convenience.
        Please use it within {ttlHours} hours.
      </Text>
      <div style={{ textAlign: 'center', margin: '30px 0' }}>
        <Button
          href={safeUrl(link)}
          style={{
            display: 'inline-block',
            backgroundColor: accent,
            color: '#ffffff',
            textDecoration: 'none',
            padding: '14px 35px',
            borderRadius: '5px',
            fontWeight: 'bold',
            fontSize: '16px',
          }}
        >
          Activate account
        </Button>
      </div>
      <Hr style={{ border: 'none', borderTop: '1px solid #eee', margin: '20px 0 0' }} />
      <Text style={{ fontSize: '14px', color: '#666', lineHeight: '1.5', padding: '15px 0 0' }}>
        If the button doesn&apos;t work, paste this link into your browser:
        <br />
        <Link
          href={safeUrl(link)}
          style={{ color: accent, textDecoration: 'underline', wordBreak: 'break-all' }}
        >
          {link}
        </Link>
      </Text>
      <Text style={{ fontSize: '16px', marginTop: '30px' }}>
        With warm regards,
        <br />
        <strong>The {portName} Team</strong>
      </Text>
    </>
  );
}

function ResetBody({
  portName,
  link,
  ttlMinutes,
  recipientName,
  accent,
}: ResetData & { accent: string }) {
  const greeting = recipientName ? `Dear ${recipientName},` : 'Hello,';

  return (
    <>
      <Text
        style={{
          marginBottom: '10px',
          fontSize: '18px',
          fontWeight: 'bold',
          color: accent,
        }}
      >
        Reset your password
      </Text>
      <Text style={{ marginBottom: '10px', fontSize: '16px', lineHeight: '1.5' }}>{greeting}</Text>
      <Text style={{ marginBottom: '20px', fontSize: '16px', lineHeight: '1.5' }}>
        We received a request to reset the password on your {portName} client portal account. Use
        the button below to choose a new one — the link will remain valid for {ttlMinutes} minutes.
      </Text>
      <div style={{ textAlign: 'center', margin: '30px 0' }}>
        <Button
          href={safeUrl(link)}
          style={{
            display: 'inline-block',
            backgroundColor: accent,
            color: '#ffffff',
            textDecoration: 'none',
            padding: '14px 35px',
            borderRadius: '5px',
            fontWeight: 'bold',
            fontSize: '16px',
          }}
        >
          Reset password
        </Button>
      </div>
      <Hr style={{ border: 'none', borderTop: '1px solid #eee', margin: '20px 0 0' }} />
      <Text style={{ fontSize: '14px', color: '#666', lineHeight: '1.5', padding: '15px 0 0' }}>
        If you didn&apos;t request this, you may safely ignore this message — your existing password
        will continue to work.
      </Text>
      <Text style={{ fontSize: '16px', marginTop: '30px' }}>
        With warm regards,
        <br />
        <strong>The {portName} Team</strong>
      </Text>
    </>
  );
}

// ─── Public surface ───────────────────────────────────────────────────────────

export async function activationEmail(
  data: ActivationData,
  overrides?: RenderOpts,
): Promise<{ subject: string; html: string; text: string }> {
  const subject = overrides?.subject
    ? overrides.subject
        .replace(/\{\{portName\}\}/g, data.portName)
        .replace(/\{\{recipientName\}\}/g, data.recipientName ?? '')
        .replace(/\{\{ttlHours\}\}/g, String(data.ttlHours))
    : `Welcome to ${data.portName} — activate your client portal`;
  const accent = brandingPrimaryColor(overrides?.branding);

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

  const text = [
    `Welcome to ${data.portName}`,
    '',
    `It's our pleasure to invite you to the ${data.portName} client portal — your private space to review your berth, manage signed documents, and stay in touch with your sales liaison.`,
    `Activate your account by visiting: ${data.link}`,
    '',
    `Please use the link within ${data.ttlHours} hours.`,
    '',
    `With warm regards,`,
    `The ${data.portName} Team`,
  ].join('\n');

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

export async function resetEmail(
  data: ResetData,
  overrides?: RenderOpts,
): Promise<{ subject: string; html: string; text: string }> {
  const subject = overrides?.subject
    ? overrides.subject
        .replace(/\{\{portName\}\}/g, data.portName)
        .replace(/\{\{recipientName\}\}/g, data.recipientName ?? '')
        .replace(/\{\{ttlMinutes\}\}/g, String(data.ttlMinutes))
    : `Reset your ${data.portName} portal password`;
  const accent = brandingPrimaryColor(overrides?.branding);

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

  const text = [
    `Reset your ${data.portName} portal password`,
    '',
    `Use the following link to choose a new password — it will remain valid for ${data.ttlMinutes} minutes:`,
    data.link,
    '',
    `If you didn't request this, you may safely ignore this message — your existing password will continue to work.`,
    '',
    `With warm regards,`,
    `The ${data.portName} Team`,
  ].join('\n');

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