import nodemailer from 'nodemailer';

const FRONTEND_URL = process.env.FRONTEND_URL || 'https://rainmakersports.app';
const FORECASTS_WELCOME_URL = `${FRONTEND_URL}/forecasts?welcome=true`;
const FORECASTS_SURVEY_URL = `${FRONTEND_URL}/forecasts?welcome=true&survey=1`;

const transporter = nodemailer.createTransport({
  sendmail: true,
  newline: 'unix',
  path: '/usr/sbin/sendmail',
});

function escapeHtml(str: string): string {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

/** Colorize O/U tokens and winner names in display_text for HTML email */
function colorizeClipHtml(text: string, clipData?: any): string {
  let html = escapeHtml(text);
  // Colorize | O | and | U | tokens
  html = html.replace(/\|\s*O\s*\|/g, '| <span style="color:#22c55e;font-weight:700;">O</span> |');
  html = html.replace(/\|\s*U\s*\|/g, '| <span style="color:#ef4444;font-weight:700;">U</span> |');
  // Colorize winner name in green if present in clip_data
  if (clipData?.winner) {
    const winner = escapeHtml(clipData.winner);
    html = html.replace(`Winner: ${winner}`, `Winner: <span style="color:#22c55e;font-weight:700;">${winner}</span>`);
  }
  return html;
}

export async function sendClipperEmail(
  email: string,
  clips: Array<{ clip_type: string; display_text: string; clipped_at: string; clip_data?: any }>
): Promise<void> {
  const now = new Date();
  const etTime = now.toLocaleString('en-US', { timeZone: 'America/New_York', dateStyle: 'medium', timeStyle: 'short' });

  const clipItems = clips
    .map(
      (c) =>
        `<li style="margin-bottom:12px;padding:12px 16px;background:#1a1f2e;border-radius:10px;border:1px solid rgba(42,48,64,0.5);">
          <span style="font-size:10px;font-weight:700;letter-spacing:0.05em;color:#4a9eff;text-transform:uppercase;">${escapeHtml(c.clip_type.replace(/_/g, ' '))}</span>
          <div style="font-family:'Courier New',Courier,monospace;font-size:14px;color:#c8d0e0;margin-top:6px;line-height:1.5;">${colorizeClipHtml(c.display_text, c.clip_data)}</div>
        </li>`
    )
    .join('');

  const html = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background:#0a0c12;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="max-width:480px;margin:0 auto;padding:40px 24px;">
    <div style="text-align:center;margin-bottom:32px;">
      <svg width="40" height="40" viewBox="0 0 24 24" fill="#4a9eff" xmlns="http://www.w3.org/2000/svg">
        <path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3h-3z"/>
      </svg>
      <h1 style="color:#ffffff;font-size:22px;margin:16px 0 4px;font-weight:800;letter-spacing:0.05em;">Your Clipper List</h1>
      <p style="color:#8b95a8;font-size:13px;margin:0;">${clips.length} item${clips.length !== 1 ? 's' : ''} clipped</p>
    </div>

    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:24px 16px;">
      <ul style="list-style:none;margin:0;padding:0;">
        ${clipItems}
      </ul>
    </div>

    <p style="color:#3a4256;font-size:11px;text-align:center;margin-top:24px;">
      Sent ${etTime} ET &mdash; Rainmaker Sports
    </p>
  </div>
</body>
</html>`;

  await transporter.sendMail({
    from: 'Rainmaker <noreply@rainmakersports.app>',
    to: email,
    subject: 'Your Clipper List',
    html,
  });
}

export async function sendVerificationEmail(email: string, token: string): Promise<void> {
  const API_URL = process.env.API_URL || FRONTEND_URL.replace(/\/$/, '') + '/api';
  const verifyUrl = `${API_URL}/auth/verify-email?token=${token}`;

  const html = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background:#0a0c12;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="max-width:480px;margin:0 auto;padding:40px 24px;">
    <div style="text-align:center;margin-bottom:32px;">
      <svg width="48" height="48" viewBox="0 0 24 24" fill="#4a9eff" xmlns="http://www.w3.org/2000/svg">
        <path d="M19.35 10.04A7.49 7.49 0 0012 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 000 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"/>
      </svg>
      <h1 style="color:#ffffff;font-size:24px;margin:16px 0 4px;">Verify Your Email</h1>
      <p style="color:#8b95a8;font-size:14px;margin:0;">Welcome to Rainmaker</p>
    </div>

    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:32px 24px;text-align:center;">
      <p style="color:#c8d0e0;font-size:15px;line-height:1.6;margin:0 0 24px;">
        Click below to verify your email and unlock your <strong style="color:#4a9eff;">free daily forecasts</strong>.
      </p>

      <a href="${verifyUrl}" style="display:inline-block;background:linear-gradient(135deg,#4a9eff,#2563eb);color:#ffffff;text-decoration:none;padding:14px 40px;border-radius:12px;font-weight:700;font-size:16px;">
        Verify Email
      </a>

      <p style="color:#5a6478;font-size:12px;margin:24px 0 0;">
        This link expires in 24 hours. If you didn't create a Rainmaker account, ignore this email.
      </p>
    </div>

    <p style="color:#3a4256;font-size:11px;text-align:center;margin-top:24px;">
      Rainmaker Sports &mdash; AI Sports Forecasting
    </p>
  </div>
</body>
</html>`;

  const text = `Verify Your Email\n\nWelcome to Rainmaker! Click the link below to verify your email and unlock your free daily forecasts.\n\n${verifyUrl}\n\nThis link expires in 24 hours. If you didn't create a Rainmaker account, ignore this email.\n\nRainmaker Sports — AI Sports Forecasting`;

  await transporter.sendMail({
    from: 'Rainmaker <noreply@rainmakersports.app>',
    to: email,
    subject: 'Verify your Rainmaker email',
    text,
    html,
  });
}

export async function sendPasswordResetEmail(email: string, token: string): Promise<void> {
  // Fragments are not sent in Referer headers, unlike query strings.
  const resetUrl = `${FRONTEND_URL}/reset-password#token=${encodeURIComponent(token)}`;

  const html = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background:#0a0c12;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="max-width:480px;margin:0 auto;padding:40px 24px;">
    <div style="text-align:center;margin-bottom:32px;">
      <svg width="48" height="48" viewBox="0 0 24 24" fill="#f97316" xmlns="http://www.w3.org/2000/svg">
        <path d="M12 1a5 5 0 00-5 5v3H6a2 2 0 00-2 2v9a2 2 0 002 2h12a2 2 0 002-2v-9a2 2 0 00-2-2h-1V6a5 5 0 00-5-5zm-3 8V6a3 3 0 016 0v3H9z"/>
      </svg>
      <h1 style="color:#ffffff;font-size:24px;margin:16px 0 4px;">Reset Your Password</h1>
      <p style="color:#8b95a8;font-size:14px;margin:0;">Rainmaker account recovery</p>
    </div>

    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:32px 24px;text-align:center;">
      <p style="color:#c8d0e0;font-size:15px;line-height:1.6;margin:0 0 24px;">
        Click below to set a new password for your Rainmaker account.
      </p>

      <a href="${resetUrl}" style="display:inline-block;background:linear-gradient(135deg,#f97316,#ea580c);color:#ffffff;text-decoration:none;padding:14px 40px;border-radius:12px;font-weight:700;font-size:16px;">
        Reset Password
      </a>

      <p style="color:#5a6478;font-size:12px;margin:24px 0 0;">
        This link expires in 1 hour. If you didn't request a reset, ignore this email.
      </p>
    </div>

    <p style="color:#3a4256;font-size:11px;text-align:center;margin-top:24px;">
      Rainmaker Sports &mdash; Account Security
    </p>
  </div>
</body>
</html>`;

  const text = `Reset Your Password\n\nSet a new password for your Rainmaker account:\n\n${resetUrl}\n\nThis link expires in 1 hour. If you didn't request a reset, ignore this email.\n\nRainmaker Sports`;

  await transporter.sendMail({
    from: 'Rainmaker <noreply@rainmakersports.app>',
    to: email,
    subject: 'Reset your Rainmaker password',
    text,
    html,
  });
}

export async function sendWelcomeEmail(email: string): Promise<void> {
  const html = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background:#0a0c12;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="max-width:480px;margin:0 auto;padding:40px 24px;">
    <div style="text-align:center;margin-bottom:32px;">
      <img src="${FRONTEND_URL}/cloud-bolt-orange-transparent.webp" alt="Rainmaker" width="80" height="80" style="display:block;margin:0 auto;" />
      <h1 style="color:#ffffff;font-size:28px;margin:16px 0 4px;font-weight:800;">Welcome to Rainmaker</h1>
      <p style="color:#f97316;font-size:15px;margin:0;font-weight:600;">Your AI Sports Forecast Edge</p>
    </div>

    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:32px 24px;">
      <p style="color:#c8d0e0;font-size:15px;line-height:1.7;margin:0 0 20px;">
        Your email is verified and your free daily forecasts are live. Do these two things first so you actually get value out of the account:
      </p>

      <div style="margin-bottom:16px;padding:12px 16px;background:rgba(249,115,22,0.06);border-radius:10px;border-left:3px solid #f97316;">
        <p style="color:#ffffff;font-size:14px;margin:0;font-weight:700;">1. Claim your bonus forecasts</p>
        <p style="color:#8b95a8;font-size:13px;margin:4px 0 0;">Complete the quick survey to unlock your daily free board plus the survey bonus.</p>
      </div>

      <div style="margin-bottom:16px;padding:12px 16px;background:rgba(249,115,22,0.06);border-radius:10px;border-left:3px solid #f97316;">
        <p style="color:#ffffff;font-size:14px;margin:0;font-weight:700;">2. Open your first forecast</p>
        <p style="color:#8b95a8;font-size:13px;margin:4px 0 0;">Jump straight into today's board and tap any matchup for the full AI read.</p>
      </div>

      <div style="margin-bottom:24px;padding:12px 16px;background:rgba(249,115,22,0.06);border-radius:10px;border-left:3px solid #f97316;">
        <p style="color:#ffffff;font-size:14px;margin:0;font-weight:700;">Free forecasts reset daily</p>
        <p style="color:#8b95a8;font-size:13px;margin:4px 0 0;">If you want the full board every day, upgrade later. Don’t worry about that now.</p>
      </div>

      <div style="text-align:center;">
        <a href="${FORECASTS_SURVEY_URL}" style="display:inline-block;background:linear-gradient(135deg,#f97316,#ea580c);color:#ffffff;text-decoration:none;padding:14px 32px;border-radius:12px;font-weight:700;font-size:16px;">
          Claim My Free Forecasts
        </a>
      </div>

      <div style="text-align:center;margin-top:12px;">
        <a href="${FORECASTS_WELCOME_URL}" style="display:inline-block;color:#f97316;text-decoration:none;font-weight:700;font-size:14px;">
          Skip straight to today's board
        </a>
      </div>
    </div>

    <p style="color:#3a4256;font-size:11px;text-align:center;margin-top:24px;">
      Rainmaker Sports &mdash; We collect the data. You enjoy the games.
    </p>
  </div>
</body>
</html>`;

  const text = `Welcome to Rainmaker!\n\nYour email is verified and your free daily forecasts are live.\n\n1. Claim your bonus forecasts: ${FORECASTS_SURVEY_URL}\n2. Open your first forecast: ${FORECASTS_WELCOME_URL}\n\nFree forecasts reset daily. Upgrade later if you want the full board every day.\n\nRainmaker Sports — We collect the data. You enjoy the games.`;

  await transporter.sendMail({
    from: 'Rainmaker <noreply@rainmakersports.app>',
    to: email,
    subject: 'Welcome to Rainmaker — Your forecasts are live',
    text,
    html,
  });
}

export async function sendPurchaseConfirmationEmail(
  email: string,
  params: { productName: string; picksGranted: number; totalBalance: number }
): Promise<void> {
  const html = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background:#0a0c12;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="max-width:480px;margin:0 auto;padding:40px 24px;">
    <div style="text-align:center;margin-bottom:32px;">
      <div style="width:56px;height:56px;border-radius:50%;background:rgba(34,197,94,0.15);display:inline-flex;align-items:center;justify-content:center;">
        <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
      </div>
      <h1 style="color:#ffffff;font-size:24px;margin:16px 0 4px;font-weight:800;">Purchase Confirmed</h1>
      <p style="color:#8b95a8;font-size:14px;margin:0;">${escapeHtml(params.productName)}</p>
    </div>

    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:32px 24px;text-align:center;">
      <p style="color:#22c55e;font-size:36px;font-weight:800;margin:0 0 4px;">+${params.picksGranted}</p>
      <p style="color:#8b95a8;font-size:14px;margin:0 0 20px;">forecasts added to your account</p>

      <div style="background:rgba(249,115,22,0.08);border:1px solid rgba(249,115,22,0.2);border-radius:10px;padding:12px;margin-bottom:24px;">
        <p style="color:#f97316;font-size:13px;font-weight:700;margin:0;">Current Balance: ${params.totalBalance} forecasts</p>
      </div>

      <a href="${FRONTEND_URL}/forecasts" style="display:inline-block;background:linear-gradient(135deg,#f97316,#ea580c);color:#ffffff;text-decoration:none;padding:14px 40px;border-radius:12px;font-weight:700;font-size:16px;">
        Use Your Forecasts
      </a>
    </div>

    <p style="color:#3a4256;font-size:11px;text-align:center;margin-top:24px;">
      Rainmaker Sports &mdash; We collect the data. You enjoy the games.
    </p>
  </div>
</body>
</html>`;

  const text = `Purchase Confirmed\n\n${params.productName}\n+${params.picksGranted} forecasts added\nCurrent balance: ${params.totalBalance} forecasts\n\nUse your forecasts: ${FRONTEND_URL}/forecasts\n\nRainmaker Sports`;

  await transporter.sendMail({
    from: 'Rainmaker <noreply@rainmakersports.app>',
    to: email,
    subject: `Purchase confirmed — +${params.picksGranted} forecasts added`,
    text,
    html,
  });
}

export async function sendMonthlyPassExpiryEmail(
  email: string,
  params: { expiresAt: string }
): Promise<void> {
  const expiresLabel = new Date(params.expiresAt).toLocaleString('en-US', {
    timeZone: 'America/New_York',
    weekday: 'short',
    month: 'short',
    day: 'numeric',
    hour: 'numeric',
    minute: '2-digit',
    timeZoneName: 'short',
  });
  const renewUrl = `${FRONTEND_URL}/pricing`;

  const html = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background:#0a0c12;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="max-width:480px;margin:0 auto;padding:40px 24px;">
    <div style="text-align:center;margin-bottom:32px;">
      <img src="${FRONTEND_URL}/cloud-bolt-orange-transparent.webp" alt="Rainmaker" width="72" height="72" style="display:block;margin:0 auto;" />
      <h1 style="color:#ffffff;font-size:26px;margin:16px 0 4px;font-weight:800;">Your Rain Man access is ending soon</h1>
      <p style="color:#8b95a8;font-size:14px;margin:0;">This plan does not auto-renew.</p>
    </div>

    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:32px 24px;text-align:center;">
      <p style="color:#c8d0e0;font-size:15px;line-height:1.7;margin:0 0 16px;">
        Your unlimited Rain Man access expires on <strong style="color:#f59e0b;">${escapeHtml(expiresLabel)}</strong>.
      </p>
      <p style="color:#8b95a8;font-size:14px;line-height:1.7;margin:0 0 24px;">
        If you want to keep unlimited forecasts and premium insights, renew manually before it ends. We do not rebill this pass automatically.
      </p>

      <a href="${renewUrl}" style="display:inline-block;background:linear-gradient(135deg,#f59e0b,#d97706);color:#000000;text-decoration:none;padding:14px 32px;border-radius:12px;font-weight:800;font-size:16px;">
        Renew Rain Man
      </a>
    </div>

    <p style="color:#3a4256;font-size:11px;text-align:center;margin-top:24px;">
      Rainmaker Sports &mdash; No silent rebills. No fake subscription language.
    </p>
  </div>
</body>
</html>`;

  const text = [
    'Your Rain Man access is ending soon.',
    '',
    `Expires: ${expiresLabel}`,
    'This plan does not auto-renew.',
    `Renew here: ${renewUrl}`,
    '',
    'Rainmaker Sports',
  ].join('\n');

  await transporter.sendMail({
    from: 'Rainmaker <noreply@rainmakersports.app>',
    to: email,
    subject: 'Rain Man access expires soon',
    text,
    html,
  });
}

export async function sendMlbAlertDigestEmail(
  email: string,
  params: {
    dateET: string;
    summary: { total_assets: number; critical_assets: number; warning_assets: number; by_code: Record<string, number> };
    issueSummary?: { total_games: number; by_issue_type: Record<string, number> };
    issues?: Array<{
      event_id: string;
      starts_at: string;
      matchup: string;
      home_team: string;
      away_team: string;
      home_feed_rows: number;
      away_feed_rows: number;
      home_candidate_count: number;
      away_candidate_count: number;
      zero_candidate_teams: string[];
      issue_type: string;
    }>;
    assets: Array<{
      event_id: string;
      forecast_type: string;
      team_side: string | null;
      team_id: string | null;
      status: string;
      starts_at: string | null;
      home_team: string | null;
      away_team: string | null;
      alerts: any[];
    }>;
  },
): Promise<void> {
  const summaryItems = Object.entries(params.summary.by_code)
    .sort((a, b) => b[1] - a[1])
    .map(([code, count]) => `<li><strong>${escapeHtml(code)}</strong>: ${count}</li>`)
    .join('');

  const issueSummaryItems = Object.entries(params.issueSummary?.by_issue_type || {})
    .sort((a, b) => b[1] - a[1])
    .map(([code, count]) => `<li><strong>${escapeHtml(code)}</strong>: ${count}</li>`)
    .join('');

  const assetItems = params.assets
    .slice(0, 20)
    .map((asset) => {
      const matchup = `${asset.away_team || '?'} @ ${asset.home_team || '?'}`;
      const alerts = asset.alerts
        .map((alert) => `<li>${escapeHtml(String(alert?.severity || 'info').toUpperCase())} — ${escapeHtml(alert?.message || alert?.code || 'Alert')}</li>`)
        .join('');
      return `
        <li style="margin-bottom:12px;padding:12px 16px;background:#1a1f2e;border-radius:10px;border:1px solid rgba(42,48,64,0.5);">
          <div style="color:#ffffff;font-weight:700;">${escapeHtml(matchup)}</div>
          <div style="color:#8b95a8;font-size:12px;margin-top:4px;">
            ${escapeHtml(asset.forecast_type)}${asset.team_side ? ` | ${escapeHtml(asset.team_side)}` : ''} | status=${escapeHtml(asset.status)}
          </div>
          <ul style="color:#c8d0e0;font-size:13px;line-height:1.5;margin:8px 0 0 18px;padding:0;">
            ${alerts}
          </ul>
        </li>`;
    })
    .join('');

  const issueItems = (params.issues || [])
    .slice(0, 20)
    .map((issue) => `
      <li style="margin-bottom:12px;padding:12px 16px;background:#1a1f2e;border-radius:10px;border:1px solid rgba(42,48,64,0.5);">
        <div style="color:#ffffff;font-weight:700;">${escapeHtml(issue.matchup)}</div>
        <div style="color:#8b95a8;font-size:12px;margin-top:4px;">
          ${escapeHtml(issue.issue_type)} | feed ${issue.home_team}:${issue.home_feed_rows} ${issue.away_team}:${issue.away_feed_rows} | candidates ${issue.home_team}:${issue.home_candidate_count} ${issue.away_team}:${issue.away_candidate_count}
        </div>
      </li>`)
    .join('');

  const html = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background:#0a0c12;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
  <div style="max-width:560px;margin:0 auto;padding:40px 24px;">
    <h1 style="color:#ffffff;font-size:24px;margin:0 0 8px;">MLB Operational Alerts</h1>
    <p style="color:#8b95a8;font-size:14px;margin:0 0 24px;">${escapeHtml(params.dateET)} ET</p>
    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:20px 24px;margin-bottom:20px;">
      <div style="color:#ffffff;font-weight:700;margin-bottom:8px;">Summary</div>
      <div style="color:#c8d0e0;font-size:14px;line-height:1.6;">
        Total assets: ${params.summary.total_assets}<br />
        Critical assets: ${params.summary.critical_assets}<br />
        Warning assets: ${params.summary.warning_assets}
      </div>
      <ul style="color:#c8d0e0;font-size:13px;line-height:1.5;margin:12px 0 0 18px;padding:0;">${summaryItems}</ul>
    </div>
    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:20px 24px;margin-bottom:20px;">
      <div style="color:#ffffff;font-weight:700;margin-bottom:8px;">Zero-Candidate Issues</div>
      <div style="color:#c8d0e0;font-size:14px;line-height:1.6;">
        Affected games: ${params.issueSummary?.total_games || 0}
      </div>
      <ul style="color:#c8d0e0;font-size:13px;line-height:1.5;margin:12px 0 0 18px;padding:0;">${issueSummaryItems || '<li>None</li>'}</ul>
      <ul style="list-style:none;margin:12px 0 0;padding:0;">${issueItems || '<li style="color:#8b95a8;">No issue rows.</li>'}</ul>
    </div>
    <div style="background:#141822;border:1px solid rgba(42,48,64,0.5);border-radius:16px;padding:20px 24px;">
      <div style="color:#ffffff;font-weight:700;margin-bottom:12px;">Affected Assets</div>
      <ul style="list-style:none;margin:0;padding:0;">${assetItems || '<li style="color:#8b95a8;">No assets.</li>'}</ul>
    </div>
  </div>
</body>
</html>`;

  const text = [
    `MLB Operational Alerts — ${params.dateET} ET`,
    `Total assets: ${params.summary.total_assets}`,
    `Critical assets: ${params.summary.critical_assets}`,
    `Warning assets: ${params.summary.warning_assets}`,
    '',
    ...Object.entries(params.summary.by_code).map(([code, count]) => `${code}: ${count}`),
    '',
    `Zero-candidate issue games: ${params.issueSummary?.total_games || 0}`,
    ...Object.entries(params.issueSummary?.by_issue_type || {}).map(([code, count]) => `${code}: ${count}`),
    '',
    ...(params.issues || []).slice(0, 20).map((issue) =>
      `${issue.matchup} | ${issue.issue_type} | feed ${issue.home_team}:${issue.home_feed_rows} ${issue.away_team}:${issue.away_feed_rows} | candidates ${issue.home_team}:${issue.home_candidate_count} ${issue.away_team}:${issue.away_candidate_count}`
    ),
    '',
    ...params.assets.slice(0, 20).map((asset) =>
      `${asset.away_team || '?'} @ ${asset.home_team || '?'} | ${asset.forecast_type}${asset.team_side ? ` | ${asset.team_side}` : ''} | ${asset.status}\n` +
      asset.alerts.map((alert) => `- ${String(alert?.severity || 'info').toUpperCase()}: ${alert?.message || alert?.code || 'Alert'}`).join('\n')
    ),
  ].join('\n');

  await transporter.sendMail({
    from: 'Rainmaker <noreply@rainmakersports.app>',
    to: email,
    subject: `MLB operational alerts (${params.summary.critical_assets} critical, ${params.summary.warning_assets} warning)`,
    text,
    html,
  });
}
