const { SESClient, SendEmailCommand } = require("@aws-sdk/client-ses");
const { getAWSConfig } = require("../../../config/aws");
const { htmlToPlainText } = require("./emailUtils");
const logger = require("../../../utils/logger");

/**
 * EmailClient handles AWS SES configuration and core email sending functionality
 * This class is responsible for:
 * - Initializing the AWS SES client
 * - Sending emails with HTML and plain text content
 * - Managing email sending state (enabled/disabled via environment)
 */
class EmailClient {
  constructor() {
    // Singleton pattern - return existing instance if already created
    if (EmailClient.instance) {
      return EmailClient.instance;
    }

    this.sesClient = null;
    this.initialized = false;
    this.initializationPromise = null;

    EmailClient.instance = this;
  }

  /**
   * Initialize the AWS SES client
   * @returns {Promise<void>}
   */
  async initialize() {
    // If already initialized, return immediately
    if (this.initialized) return;

    // If initialization is in progress, wait for it
    if (this.initializationPromise) {
      return this.initializationPromise;
    }

    // Start initialization and store the promise
    this.initializationPromise = (async () => {
      try {
        // Use centralized AWS configuration with credential profiles
        const awsConfig = getAWSConfig();
        this.sesClient = new SESClient(awsConfig);

        this.initialized = true;
        logger.info("AWS SES Email Client initialized successfully");
      } catch (error) {
        logger.error("Failed to initialize AWS SES Email Client", { error });
        throw error;
      }
    })();

    return this.initializationPromise;
  }

  /**
   * Send an email using AWS SES
   * @param {string|string[]} to - Email address(es) to send to
   * @param {string} subject - Email subject line
   * @param {string} htmlContent - HTML content of the email
   * @param {string|null} textContent - Plain text content (auto-generated from HTML if not provided)
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendEmail(to, subject, htmlContent, textContent = null) {
    if (!this.initialized) {
      await this.initialize();
    }

    // Check if email sending is enabled in the environment
    if (!process.env.EMAIL_ENABLED || process.env.EMAIL_ENABLED !== "true") {
      logger.debug("Email sending disabled in environment");
      return { success: true, messageId: "disabled" };
    }

    // Auto-generate plain text from HTML if not provided
    if (!textContent) {
      textContent = htmlToPlainText(htmlContent);
    }

    // Use friendly sender name format for better recognition
    const fromName = process.env.SES_FROM_NAME || "Village Share";
    const fromEmail = process.env.SES_FROM_EMAIL;
    const source = `${fromName} <${fromEmail}>`;

    const params = {
      Source: source,
      Destination: {
        ToAddresses: Array.isArray(to) ? to : [to],
      },
      Message: {
        Subject: {
          Data: subject,
          Charset: "UTF-8",
        },
        Body: {
          Html: {
            Data: htmlContent,
            Charset: "UTF-8",
          },
          Text: {
            Data: textContent,
            Charset: "UTF-8",
          },
        },
      },
    };

    // Add reply-to address if configured
    if (process.env.SES_REPLY_TO_EMAIL) {
      params.ReplyToAddresses = [process.env.SES_REPLY_TO_EMAIL];
    }

    try {
      const command = new SendEmailCommand(params);
      const result = await this.sesClient.send(command);

      logger.info("Email sent successfully", { to, messageId: result.MessageId });
      return { success: true, messageId: result.MessageId };
    } catch (error) {
      logger.error("Failed to send email", { error, to });
      return { success: false, error: error.message };
    }
  }
}

module.exports = EmailClient;
