import nodemailer from 'nodemailer';
import { getSystemConfig } from './config';

export interface InlineAttachment {
  filename: string
  content: Buffer
  cid: string
}

interface MailOptions {
  to: string;
  subject: string;
  html: string;
  attachments?: InlineAttachment[];
}

interface MailResult {
  success: boolean;
  messageId?: string;
  error?: string;
}

type EmailProvider = 'auto' | 'resend' | 'smtp';

/**
 * Send email.
 * - 'auto': try Resend first (if key set), fall back to SMTP on failure
 * - 'smtp': force SMTP only
 * - 'resend': force Resend only
 * Supports inline image attachments via cid: references in HTML.
 */
export async function sendEmail({ to, subject, html, attachments }: MailOptions, provider: EmailProvider = 'auto'): Promise<MailResult> {
  const config = await getSystemConfig();
  const resendKey = config.RESEND_API_KEY || process.env.RESEND_API_KEY;

  // Force SMTP
  if (provider === 'smtp') {
    return sendViaSMTP(config, { to, subject, html, attachments });
  }

  // Force Resend (no fallback)
  if (provider === 'resend') {
    if (!resendKey) return { success: false, error: 'No Resend API key configured' };
    return sendViaResend(resendKey, { to, subject, html, attachments });
  }

  // Auto: try Resend, fall back to SMTP
  if (resendKey) {
    const result = await sendViaResend(resendKey, { to, subject, html, attachments });
    if (result.success) return result;

    console.warn('[Mail] Resend failed, falling back to SMTP:', result.error);
    return sendViaSMTP(config, { to, subject, html, attachments });
  }

  return sendViaSMTP(config, { to, subject, html, attachments });
}

async function sendViaResend(apiKey: string, { to, subject, html, attachments }: MailOptions): Promise<MailResult> {
  try {
    const { Resend } = await import('resend');
    const resend = new Resend(apiKey);

    const hostname = process.env.NEXTAUTH_URL ? new URL(process.env.NEXTAUTH_URL).hostname : '';
    const from = hostname && hostname !== 'localhost'
      ? `Memento <noreply@${hostname}>`
      : 'Memento <onboarding@resend.dev>';

    // Resend supports attachments with inline content
    const resendAttachments = attachments?.map(att => ({
      filename: att.filename,
      content: att.content.toString('base64'),
      content_type: att.filename.endsWith('.png') ? 'image/png' : 'image/jpeg',
      disposition: 'inline' as const,
      content_id: att.cid,
    }));

    const { data, error } = await resend.emails.send({
      from,
      to,
      subject,
      html,
      attachments: resendAttachments,
    });

    if (error) {
      return { success: false, error: error.message };
    }

    return { success: true, messageId: data?.id };
  } catch (error: any) {
    return { success: false, error: `Resend: ${error.message}` };
  }
}

async function sendViaSMTP(config: Record<string, string>, { to, subject, html, attachments }: MailOptions): Promise<MailResult> {
  const host = config.SMTP_HOST || process.env.SMTP_HOST;
  const port = parseInt(config.SMTP_PORT || process.env.SMTP_PORT || '587');
  const user = (config.SMTP_USER || process.env.SMTP_USER || '').trim();
  const pass = (config.SMTP_PASS || process.env.SMTP_PASS || '').trim();
  const from = config.SMTP_FROM || process.env.SMTP_FROM || 'noreply@memento.app';

  if (!host) {
    return { success: false, error: 'SMTP host is not configured' };
  }

  const forceSecure = config.SMTP_SECURE === 'true';
  const isPort465 = port === 465;
  const secure = forceSecure || isPort465;
  const ignoreCerts = config.SMTP_IGNORE_CERT === 'true';

  const transporter = nodemailer.createTransport({
    host,
    port,
    secure,
    auth: { user, pass },
    family: 4,
    authMethod: 'LOGIN',
    connectionTimeout: 10000,
    tls: {
      rejectUnauthorized: !ignoreCerts,
      ciphers: ignoreCerts ? 'SSLv3' : undefined
    }
  } as any);

  try {
    await transporter.verify();

    // Build nodemailer inline attachments with cid
    const smtpAttachments = attachments?.map(att => ({
      filename: att.filename,
      content: att.content,
      cid: att.cid,
    }));

    const info = await transporter.sendMail({
      from: `"Memento" <${from}>`,
      to,
      subject,
      html,
      attachments: smtpAttachments,
    });
    return { success: true, messageId: info.messageId };
  } catch (error: any) {
    console.error('SMTP error:', error);
    return { success: false, error: `SMTP: ${error.message} (Code: ${error.code})` };
  }
}
