const EmailClient = require("../core/EmailClient");
const TemplateManager = require("../core/TemplateManager");
const logger = require("../../../utils/logger");

/**
 * ForumEmailService handles all forum-related email notifications
 * This service is responsible for:
 * - Sending comment notifications to post authors
 * - Sending reply notifications to comment authors
 * - Sending answer accepted notifications
 * - Sending thread activity notifications to participants
 * - Sending location-based item request notifications to nearby users
 * - Sending post/comment deletion notifications to authors
 */
class ForumEmailService {
  constructor() {
    this.emailClient = new EmailClient();
    this.templateManager = new TemplateManager();
    this.initialized = false;
  }

  /**
   * Initialize the forum email service
   * @returns {Promise<void>}
   */
  async initialize() {
    if (this.initialized) return;

    await Promise.all([
      this.emailClient.initialize(),
      this.templateManager.initialize(),
    ]);

    this.initialized = true;
    logger.info("Forum Email Service initialized successfully");
  }

  /**
   * Send notification when someone comments on a post
   * @param {Object} postAuthor - Post author user object
   * @param {string} postAuthor.firstName - Post author's first name
   * @param {string} postAuthor.email - Post author's email
   * @param {Object} commenter - Commenter user object
   * @param {string} commenter.firstName - Commenter's first name
   * @param {string} commenter.lastName - Commenter's last name
   * @param {Object} post - Forum post object
   * @param {number} post.id - Post ID
   * @param {string} post.title - Post title
   * @param {Object} comment - Comment object
   * @param {string} comment.content - Comment content
   * @param {Date} comment.createdAt - Comment creation timestamp
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendForumCommentNotification(postAuthor, commenter, post, comment) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const postUrl = `${frontendUrl}/forum/posts/${post.id}`;

      const timestamp = new Date(comment.createdAt).toLocaleString("en-US", {
        dateStyle: "medium",
        timeStyle: "short",
      });

      const variables = {
        postAuthorName: postAuthor.firstName || "there",
        commenterName:
          `${commenter.firstName} ${commenter.lastName}`.trim() || "Someone",
        postTitle: post.title,
        commentContent: comment.content,
        postUrl: postUrl,
        timestamp: timestamp,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumCommentToPostAuthor",
        variables
      );

      const subject = `${commenter.firstName} ${commenter.lastName} commented on your post`;

      const result = await this.emailClient.sendEmail(
        postAuthor.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Forum comment notification email sent to ${postAuthor.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error("Failed to send forum comment notification email:", error);
      return { success: false, error: error.message };
    }
  }

  /**
   * Send notification when someone replies to a comment
   * @param {Object} commentAuthor - Original comment author user object
   * @param {string} commentAuthor.firstName - Comment author's first name
   * @param {string} commentAuthor.email - Comment author's email
   * @param {Object} replier - Replier user object
   * @param {string} replier.firstName - Replier's first name
   * @param {string} replier.lastName - Replier's last name
   * @param {Object} post - Forum post object
   * @param {number} post.id - Post ID
   * @param {string} post.title - Post title
   * @param {Object} reply - Reply comment object
   * @param {string} reply.content - Reply content
   * @param {Date} reply.createdAt - Reply creation timestamp
   * @param {Object} parentComment - Parent comment being replied to
   * @param {string} parentComment.content - Parent comment content
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendForumReplyNotification(
    commentAuthor,
    replier,
    post,
    reply,
    parentComment
  ) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const postUrl = `${frontendUrl}/forum/posts/${post.id}`;

      const timestamp = new Date(reply.createdAt).toLocaleString("en-US", {
        dateStyle: "medium",
        timeStyle: "short",
      });

      const variables = {
        commentAuthorName: commentAuthor.firstName || "there",
        replierName:
          `${replier.firstName} ${replier.lastName}`.trim() || "Someone",
        postTitle: post.title,
        parentCommentContent: parentComment.content,
        replyContent: reply.content,
        postUrl: postUrl,
        timestamp: timestamp,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumReplyToCommentAuthor",
        variables
      );

      const subject = `${replier.firstName} ${replier.lastName} replied to your comment`;

      const result = await this.emailClient.sendEmail(
        commentAuthor.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Forum reply notification email sent to ${commentAuthor.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error("Failed to send forum reply notification email:", error);
      return { success: false, error: error.message };
    }
  }

  /**
   * Send notification when a comment is marked as the accepted answer
   * @param {Object} commentAuthor - Comment author user object
   * @param {string} commentAuthor.firstName - Comment author's first name
   * @param {string} commentAuthor.email - Comment author's email
   * @param {Object} postAuthor - Post author user object who accepted the answer
   * @param {string} postAuthor.firstName - Post author's first name
   * @param {string} postAuthor.lastName - Post author's last name
   * @param {Object} post - Forum post object
   * @param {number} post.id - Post ID
   * @param {string} post.title - Post title
   * @param {Object} comment - Comment that was accepted as answer
   * @param {string} comment.content - Comment content
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendForumAnswerAcceptedNotification(
    commentAuthor,
    postAuthor,
    post,
    comment
  ) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const postUrl = `${frontendUrl}/forum/posts/${post.id}`;

      const variables = {
        commentAuthorName: commentAuthor.firstName || "there",
        postAuthorName:
          `${postAuthor.firstName} ${postAuthor.lastName}`.trim() || "Someone",
        postTitle: post.title,
        commentContent: comment.content,
        postUrl: postUrl,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumAnswerAcceptedToCommentAuthor",
        variables
      );

      const subject = `Your comment was marked as the accepted answer!`;

      const result = await this.emailClient.sendEmail(
        commentAuthor.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Forum answer accepted notification email sent to ${commentAuthor.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error(
        "Failed to send forum answer accepted notification email:",
        error
      );
      return { success: false, error: error.message };
    }
  }

  /**
   * Send notification to thread participants about new activity
   * @param {Object} participant - Participant user object
   * @param {string} participant.firstName - Participant's first name
   * @param {string} participant.email - Participant's email
   * @param {Object} commenter - User who posted new comment
   * @param {string} commenter.firstName - Commenter's first name
   * @param {string} commenter.lastName - Commenter's last name
   * @param {Object} post - Forum post object
   * @param {number} post.id - Post ID
   * @param {string} post.title - Post title
   * @param {Object} comment - New comment/activity
   * @param {string} comment.content - Comment content
   * @param {Date} comment.createdAt - Comment creation timestamp
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendForumThreadActivityNotification(
    participant,
    commenter,
    post,
    comment
  ) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const postUrl = `${frontendUrl}/forum/posts/${post.id}`;

      const timestamp = new Date(comment.createdAt).toLocaleString("en-US", {
        dateStyle: "medium",
        timeStyle: "short",
      });

      const variables = {
        participantName: participant.firstName || "there",
        commenterName:
          `${commenter.firstName} ${commenter.lastName}`.trim() || "Someone",
        postTitle: post.title,
        commentContent: comment.content,
        postUrl: postUrl,
        timestamp: timestamp,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumThreadActivityToParticipant",
        variables
      );

      const subject = `New activity on a post you're following`;

      const result = await this.emailClient.sendEmail(
        participant.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Forum thread activity notification email sent to ${participant.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error(
        "Failed to send forum thread activity notification email:",
        error
      );
      return { success: false, error: error.message };
    }
  }

  /**
   * Send notification when a discussion is closed
   * @param {Object} recipient - Recipient user object
   * @param {string} recipient.firstName - Recipient's first name
   * @param {string} recipient.email - Recipient's email
   * @param {Object} closer - User who closed the discussion (can be admin or post author)
   * @param {string} closer.firstName - Closer's first name
   * @param {string} closer.lastName - Closer's last name
   * @param {Object} post - Forum post object
   * @param {number} post.id - Post ID
   * @param {string} post.title - Post title
   * @param {Date} closedAt - Timestamp when discussion was closed
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendForumPostClosedNotification(
    recipient,
    closer,
    post,
    closedAt
  ) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const postUrl = `${frontendUrl}/forum/posts/${post.id}`;

      const timestamp = new Date(closedAt).toLocaleString("en-US", {
        dateStyle: "medium",
        timeStyle: "short",
      });

      const variables = {
        recipientName: recipient.firstName || "there",
        adminName:
          `${closer.firstName} ${closer.lastName}`.trim() || "A user",
        postTitle: post.title,
        postUrl: postUrl,
        timestamp: timestamp,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumPostClosed",
        variables
      );

      const subject = `Discussion closed: ${post.title}`;

      const result = await this.emailClient.sendEmail(
        recipient.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Forum post closed notification email sent to ${recipient.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error(
        "Failed to send forum post closed notification email:",
        error
      );
      return { success: false, error: error.message };
    }
  }

  /**
   * Send notification when a forum post is deleted by admin
   * @param {Object} postAuthor - Post author user object
   * @param {string} postAuthor.firstName - Post author's first name
   * @param {string} postAuthor.email - Post author's email
   * @param {Object} admin - Admin user object who deleted the post
   * @param {string} admin.firstName - Admin's first name
   * @param {string} admin.lastName - Admin's last name
   * @param {Object} post - Forum post object
   * @param {string} post.title - Post title
   * @param {string} deletionReason - Reason for deletion
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendForumPostDeletionNotification(postAuthor, admin, post, deletionReason) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const supportEmail = process.env.SUPPORT_EMAIL;
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";

      const variables = {
        postAuthorName: postAuthor.firstName || "there",
        adminName: `${admin.firstName} ${admin.lastName}`.trim() || "An administrator",
        postTitle: post.title,
        deletionReason,
        supportEmail,
        forumUrl: `${frontendUrl}/forum`,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumPostDeletionToAuthor",
        variables
      );

      const subject = `Important: Your forum post "${post.title}" has been removed`;

      const result = await this.emailClient.sendEmail(
        postAuthor.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Forum post deletion notification email sent to ${postAuthor.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error(
        "Failed to send forum post deletion notification email:",
        error
      );
      return { success: false, error: error.message };
    }
  }

  /**
   * Send notification when a forum comment is deleted by admin
   * @param {Object} commentAuthor - Comment author user object
   * @param {string} commentAuthor.firstName - Comment author's first name
   * @param {string} commentAuthor.email - Comment author's email
   * @param {Object} admin - Admin user object who deleted the comment
   * @param {string} admin.firstName - Admin's first name
   * @param {string} admin.lastName - Admin's last name
   * @param {Object} post - Forum post object the comment belongs to
   * @param {string} post.title - Post title
   * @param {string} post.id - Post ID
   * @param {string} deletionReason - Reason for deletion
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendForumCommentDeletionNotification(commentAuthor, admin, post, deletionReason) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const supportEmail = process.env.SUPPORT_EMAIL;
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const postUrl = `${frontendUrl}/forum/posts/${post.id}`;

      const variables = {
        commentAuthorName: commentAuthor.firstName || "there",
        adminName: `${admin.firstName} ${admin.lastName}`.trim() || "An administrator",
        postTitle: post.title,
        postUrl,
        deletionReason,
        supportEmail,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumCommentDeletionToAuthor",
        variables
      );

      const subject = `Your comment on "${post.title}" has been removed`;

      const result = await this.emailClient.sendEmail(
        commentAuthor.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Forum comment deletion notification email sent to ${commentAuthor.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error(
        "Failed to send forum comment deletion notification email:",
        error
      );
      return { success: false, error: error.message };
    }
  }

  /**
   * Send notification to nearby users about an item request
   * @param {Object} recipient - Recipient user object
   * @param {string} recipient.firstName - Recipient's first name
   * @param {string} recipient.email - Recipient's email
   * @param {Object} requester - User who posted the item request
   * @param {string} requester.firstName - Requester's first name
   * @param {string} requester.lastName - Requester's last name
   * @param {Object} post - Forum post object (item request)
   * @param {number} post.id - Post ID
   * @param {string} post.title - Item being requested
   * @param {string} post.content - Request description
   * @param {string|number} distance - Distance from recipient to request location (in miles)
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendItemRequestNotification(recipient, requester, post, distance) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const postUrl = `${frontendUrl}/forum/posts/${post.id}`;

      const variables = {
        recipientName: recipient.firstName || "there",
        requesterName:
          `${requester.firstName} ${requester.lastName}`.trim() || "Someone",
        itemRequested: post.title,
        requestDescription: post.content,
        postUrl: postUrl,
        distance: distance,
      };

      const htmlContent = await this.templateManager.renderTemplate(
        "forumItemRequestNotification",
        variables
      );

      const subject = `Someone nearby is looking for: ${post.title}`;

      const result = await this.emailClient.sendEmail(
        recipient.email,
        subject,
        htmlContent
      );

      if (result.success) {
        logger.info(
          `Item request notification email sent to ${recipient.email}`
        );
      }

      return result;
    } catch (error) {
      logger.error("Failed to send item request notification email:", error);
      return { success: false, error: error.message };
    }
  }
}

module.exports = ForumEmailService;
