import * as nodemailer from "nodemailer";
import { prisma } from "~/utils/db.server";
import { decryptMailSettings } from "~/utils/encryption.server";

interface EmailOptions {
  to: string | string[];
  subject: string;
  text?: string;
  html?: string;
  attachments?: Array<{
    filename: string;
    content: Buffer | string;
    contentType?: string;
  }>;
}

export async function sendEmail(options: EmailOptions) {
  try {
    // Get mail settings from database
    const encryptedMailSettings = await prisma.mailSettings.findFirst();
    
    if (!encryptedMailSettings) {
      throw new Error("Mail settings not configured. Please configure SMTP settings first.");
    }
    
    // Decrypt the mail settings
    const mailSettings = decryptMailSettings(encryptedMailSettings);
    
    // Create transporter with enhanced configuration
    const transportConfig: any = {
      host: mailSettings.host,
      port: mailSettings.port,
      secure: mailSettings.secure,
      auth: {
        user: mailSettings.username,
        pass: mailSettings.password, // Now decrypted
      },
    };
    
    // Add additional options for better compatibility
    if (!mailSettings.secure && mailSettings.port === 587) {
      transportConfig.requireTLS = true;
      transportConfig.tls = {
        ciphers: 'SSLv3'
      };
    }
    
    // Add timeout settings
    transportConfig.connectionTimeout = 10000;
    transportConfig.greetingTimeout = 5000;
    transportConfig.socketTimeout = 10000;
    
    const transporter = nodemailer.createTransport(transportConfig);
    
    // Verify connection
    await transporter.verify();
    
    // Send email
    const result = await transporter.sendMail({
      from: `"${mailSettings.fromName}" <${mailSettings.fromEmail}>`,
      to: Array.isArray(options.to) ? options.to.join(", ") : options.to,
      subject: options.subject,
      text: options.text,
      html: options.html,
      attachments: options.attachments,
    });
    
    return {
      success: true,
      messageId: result.messageId,
      response: result.response,
    };
  } catch (error) {
    console.error("Failed to send email:", error);
    return {
      success: false,
      error: error instanceof Error ? error.message : "Unknown error occurred",
    };
  }
}

export async function testEmailConnection() {
  try {
    const encryptedMailSettings = await prisma.mailSettings.findFirst();
    
    if (!encryptedMailSettings) {
      return {
        success: false,
        error: "Mail settings not configured",
      };
    }
    
    // Decrypt the mail settings
    const mailSettings = decryptMailSettings(encryptedMailSettings);
    
    const transportConfig: any = {
      host: mailSettings.host,
      port: mailSettings.port,
      secure: mailSettings.secure, // true for 465, false for other ports
      auth: {
        user: mailSettings.username,
        pass: mailSettings.password, // Now decrypted
      },
    };
    
    // Add additional options for better compatibility
    if (!mailSettings.secure && mailSettings.port === 587) {
      transportConfig.requireTLS = true;
      transportConfig.tls = {
        ciphers: 'SSLv3'
      };
    }
    
    // Add timeout settings
    transportConfig.connectionTimeout = 10000; // 10 seconds
    transportConfig.greetingTimeout = 5000; // 5 seconds
    transportConfig.socketTimeout = 10000; // 10 seconds
    
    console.log('Testing SMTP connection with config:', {
      host: mailSettings.host,
      port: mailSettings.port,
      secure: mailSettings.secure,
      user: mailSettings.username
    });
    
    const transporter = nodemailer.createTransport(transportConfig);
    
    await transporter.verify();
    
    return {
      success: true,
      message: "SMTP connection successful",
    };
  } catch (error) {
    console.error('SMTP connection error:', error);
    return {
      success: false,
      error: error instanceof Error ? error.message : "Connection failed",
    };
  }
}

// Helper function to send notification emails
export async function sendNotificationEmail(
  to: string | string[],
  subject: string,
  message: string,
  isHtml: boolean = false
) {
  const emailOptions: EmailOptions = {
    to,
    subject,
  };
  
  if (isHtml) {
    emailOptions.html = message;
  } else {
    emailOptions.text = message;
  }
  
  return await sendEmail(emailOptions);
}

// Helper function to send report emails with attachments
export async function sendReportEmail(
  to: string | string[],
  subject: string,
  reportData: any,
  attachments?: Array<{
    filename: string;
    content: Buffer | string;
    contentType?: string;
  }>
) {
  const htmlContent = `
    <h2>${subject}</h2>
    <p>Please find the report details below:</p>
    <pre>${JSON.stringify(reportData, null, 2)}</pre>
  `;
  
  return await sendEmail({
    to,
    subject,
    html: htmlContent,
    attachments,
  });
}

// Utility function to clean up expired password reset tokens
export async function cleanupExpiredTokens() {
  try {
    const result = await prisma.passwordResetToken.deleteMany({
      where: {
        OR: [
          { expiresAt: { lt: new Date() } },
          { used: true }
        ]
      }
    });
    
    console.log(`Cleaned up ${result.count} expired/used password reset tokens`);
    return result.count;
  } catch (error) {
    console.error("Failed to cleanup expired tokens:", error);
    return 0;
  }
}