// Email transport layer: provider configuration, SMTP setup, and the low-level
// sendEmail router. No template rendering or DB logging happens here.

import nodemailer from 'nodemailer';
import type { Transporter } from 'nodemailer';

// ==================== Types ====================

export interface SendEmailOptions {
  to: string | string[];
  subject: string;
  html: string;
  text?: string;
  replyTo?: string;
}

export interface SendEmailResult {
  success: boolean;
  messageId?: string;
  error?: string;
}

export type EmailProvider = 'resend' | 'smtp' | 'console';

// ==================== Provider Configuration ====================

function getEmailProvider(): EmailProvider {
  const provider = (process.env.EMAIL_PROVIDER || 'console').toLowerCase();
  if (provider === 'resend' || provider === 'smtp' || provider === 'console') {
    return provider;
  }
  console.warn(`[Email] Unknown provider "${provider}", falling back to console`);
  return 'console';
}

function getFromEmail(): string {
  return process.env.EMAIL_FROM || 'noreply@spanglish.com';
}

function getFromName(): string {
  return process.env.EMAIL_FROM_NAME || 'Spanglish';
}

/** Provider info for diagnostics endpoints. */
export function getProviderInfo(): { provider: EmailProvider; configured: boolean } {
  const provider = getEmailProvider();
  let configured = false;

  switch (provider) {
    case 'resend':
      configured = !!(process.env.EMAIL_API_KEY || process.env.RESEND_API_KEY);
      break;
    case 'smtp':
      configured = !!process.env.SMTP_HOST;
      break;
    case 'console':
      configured = true;
      break;
  }

  return { provider, configured };
}

// ==================== SMTP Configuration ====================

interface SMTPConfig {
  host: string;
  port: number;
  secure: boolean;
  auth?: {
    user: string;
    pass: string;
  };
}

function getSMTPConfig(): SMTPConfig | null {
  const host = process.env.SMTP_HOST;
  const port = parseInt(process.env.SMTP_PORT || '587');
  const user = process.env.SMTP_USER;
  const pass = process.env.SMTP_PASS;
  const secure = process.env.SMTP_SECURE === 'true' || port === 465;

  if (!host) {
    return null;
  }

  const config: SMTPConfig = {
    host,
    port,
    secure,
  };

  if (user && pass) {
    config.auth = { user, pass };
  }

  return config;
}

// Cached SMTP transporter
let smtpTransporter: Transporter | null = null;

function getSMTPTransporter(): Transporter | null {
  if (smtpTransporter) {
    return smtpTransporter;
  }

  const config = getSMTPConfig();
  if (!config) {
    console.error('[Email] SMTP configuration missing');
    return null;
  }

  smtpTransporter = nodemailer.createTransport({
    host: config.host,
    port: config.port,
    secure: config.secure,
    auth: config.auth,
    // Additional options for better deliverability
    pool: true,
    maxConnections: 5,
    maxMessages: 100,
    // TLS options
    tls: {
      rejectUnauthorized: process.env.SMTP_TLS_REJECT_UNAUTHORIZED !== 'false',
    },
  });

  // Verify connection configuration
  smtpTransporter.verify((error, success) => {
    if (error) {
      console.error('[Email] SMTP connection verification failed:', error.message);
    } else {
      console.log('[Email] SMTP server is ready to send emails');
    }
  });

  return smtpTransporter;
}

// ==================== Email Providers ====================

/**
 * Send email using Resend API
 */
async function sendWithResend(options: SendEmailOptions): Promise<SendEmailResult> {
  const apiKey = process.env.EMAIL_API_KEY || process.env.RESEND_API_KEY;
  const fromEmail = getFromEmail();
  const fromName = getFromName();

  if (!apiKey) {
    console.error('[Email] Resend API key not configured');
    return { success: false, error: 'Resend API key not configured' };
  }

  try {
    const response = await fetch('https://api.resend.com/emails', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        from: `${fromName} <${fromEmail}>`,
        to: Array.isArray(options.to) ? options.to : [options.to],
        subject: options.subject,
        html: options.html,
        text: options.text,
        reply_to: options.replyTo,
      }),
    });

    const data = await response.json();

    if (!response.ok) {
      console.error('[Email] Resend API error:', data);
      return {
        success: false,
        error: data.message || data.error || 'Failed to send email'
      };
    }

    console.log('[Email] Email sent via Resend:', data.id);
    return {
      success: true,
      messageId: data.id
    };
  } catch (error: any) {
    console.error('[Email] Resend error:', error);
    return {
      success: false,
      error: error.message || 'Failed to send email via Resend'
    };
  }
}

/**
 * Send email using SMTP (Nodemailer)
 */
async function sendWithSMTP(options: SendEmailOptions): Promise<SendEmailResult> {
  const transporter = getSMTPTransporter();

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

  const fromEmail = getFromEmail();
  const fromName = getFromName();

  try {
    const info = await transporter.sendMail({
      from: `"${fromName}" <${fromEmail}>`,
      to: Array.isArray(options.to) ? options.to.join(', ') : options.to,
      replyTo: options.replyTo,
      subject: options.subject,
      html: options.html,
      text: options.text,
    });

    console.log('[Email] Email sent via SMTP:', info.messageId);
    return {
      success: true,
      messageId: info.messageId
    };
  } catch (error: any) {
    console.error('[Email] SMTP error:', error);
    return {
      success: false,
      error: error.message || 'Failed to send email via SMTP'
    };
  }
}

/**
 * Console logger for development/testing (no actual email sent)
 */
async function sendWithConsole(options: SendEmailOptions): Promise<SendEmailResult> {
  const to = Array.isArray(options.to) ? options.to.join(', ') : options.to;

  console.log('\n========================================');
  console.log('[Email] Console Mode - Email Preview');
  console.log('========================================');
  console.log(`To: ${to}`);
  console.log(`Subject: ${options.subject}`);
  console.log(`Reply-To: ${options.replyTo || 'N/A'}`);
  console.log('----------------------------------------');
  console.log('HTML Body (truncated):');
  console.log(options.html?.substring(0, 500) + '...');
  console.log('========================================\n');

  return {
    success: true,
    messageId: `console-${Date.now()}`
  };
}

// Mask an email address for logs: keep first char + domain (e.g. j***@example.com).
function maskEmail(email: string): string {
  const [local, domain] = String(email).split('@');
  if (!domain) return '***';
  const head = local.slice(0, 1);
  return `${head}***@${domain}`;
}

/**
 * Main send function that routes to the appropriate provider
 */
export async function sendEmail(options: SendEmailOptions): Promise<SendEmailResult> {
  const provider = getEmailProvider();

  const recipientCount = Array.isArray(options.to) ? options.to.length : 1;
  const sample = Array.isArray(options.to) ? options.to[0] : options.to;
  console.log(`[Email] Sending email via ${provider} to ${maskEmail(sample)}${recipientCount > 1 ? ` (+${recipientCount - 1} more)` : ''}`);

  switch (provider) {
    case 'resend':
      return sendWithResend(options);
    case 'smtp':
      return sendWithSMTP(options);
    case 'console':
    default:
      return sendWithConsole(options);
  }
}

/**
 * Test email configuration by sending a test email
 */
export async function testConnection(to: string): Promise<SendEmailResult> {
  const { provider, configured } = getProviderInfo();

  if (!configured) {
    return { success: false, error: `Email provider "${provider}" is not configured` };
  }

  return sendEmail({
    to,
    subject: 'Spanglish - Email Test',
    html: `
        <h2>Email Configuration Test</h2>
        <p>This is a test email from your Spanglish platform.</p>
        <p><strong>Provider:</strong> ${provider}</p>
        <p><strong>Timestamp:</strong> ${new Date().toISOString()}</p>
        <p>If you received this email, your email configuration is working correctly!</p>
      `,
    text: `Email Configuration Test\n\nProvider: ${provider}\nTimestamp: ${new Date().toISOString()}\n\nIf you received this email, your email configuration is working correctly!`,
  });
}
