const fs = require("fs").promises;
const path = require("path");
const logger = require("../../../utils/logger");

/**
 * TemplateManager handles loading, caching, and rendering email templates
 * This class is responsible for:
 * - Loading HTML email templates from disk
 * - Caching templates in memory for performance
 * - Rendering templates with variable substitution
 * - Providing fallback templates when files can't be loaded
 */
class TemplateManager {
  constructor() {
    // Singleton pattern - return existing instance if already created
    if (TemplateManager.instance) {
      return TemplateManager.instance;
    }

    this.templates = new Map();
    this.initialized = false;
    this.initializationPromise = null;

    TemplateManager.instance = this;
  }

  /**
   * Initialize the template manager by loading all email templates
   * @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 () => {
      await this.loadEmailTemplates();
      this.initialized = true;
      logger.info("Email Template Manager initialized successfully");
    })();

    return this.initializationPromise;
  }

  /**
   * Load all email templates from disk into memory
   * @returns {Promise<void>}
   */
  async loadEmailTemplates() {
    const templatesDir = path.join(
      __dirname,
      "..",
      "..",
      "..",
      "templates",
      "emails"
    );

    // Critical templates that must load for the app to function
    const criticalTemplates = [
      "emailVerificationToUser.html",
      "passwordResetToUser.html",
      "passwordChangedToUser.html",
      "personalInfoChangedToUser.html",
    ];

    try {
      const templateFiles = [
        "conditionCheckReminderToUser.html",
        "rentalConfirmationToUser.html",
        "emailVerificationToUser.html",
        "passwordResetToUser.html",
        "passwordChangedToUser.html",
        "personalInfoChangedToUser.html",
        "lateReturnToCS.html",
        "damageReportToCS.html",
        "lostItemToCS.html",
        "rentalRequestToOwner.html",
        "rentalRequestConfirmationToRenter.html",
        "rentalCancellationConfirmationToUser.html",
        "rentalCancellationNotificationToUser.html",
        "rentalDeclinedToRenter.html",
        "rentalApprovalConfirmationToOwner.html",
        "rentalCompletionThankYouToRenter.html",
        "rentalCompletionCongratsToOwner.html",
        "payoutReceivedToOwner.html",
        "firstListingCelebrationToOwner.html",
        "itemDeletionToOwner.html",
        "alphaInvitationToUser.html",
        "feedbackConfirmationToUser.html",
        "feedbackNotificationToAdmin.html",
        "newMessageToUser.html",
        "forumCommentToPostAuthor.html",
        "forumReplyToCommentAuthor.html",
        "forumAnswerAcceptedToCommentAuthor.html",
        "forumThreadActivityToParticipant.html",
        "forumPostClosed.html",
        "forumItemRequestNotification.html",
        "forumPostDeletionToAuthor.html",
        "forumCommentDeletionToAuthor.html",
        "paymentDeclinedToRenter.html",
        "paymentMethodUpdatedToOwner.html",
        "authenticationRequiredToRenter.html",
        "payoutFailedToOwner.html",
        "accountDisconnectedToOwner.html",
        "payoutsDisabledToOwner.html",
        "disputeAlertToAdmin.html",
        "disputeLostAlertToAdmin.html",
        "userBannedNotification.html",
      ];

      const failedTemplates = [];

      for (const templateFile of templateFiles) {
        try {
          const templatePath = path.join(templatesDir, templateFile);
          const templateContent = await fs.readFile(templatePath, "utf-8");
          const templateName = path.basename(templateFile, ".html");
          this.templates.set(templateName, templateContent);
          logger.debug("Loaded template", { templateName });
        } catch (error) {
          logger.error("Failed to load template", {
            templateFile,
            templatePath: path.join(templatesDir, templateFile),
            error,
          });
          failedTemplates.push(templateFile);
        }
      }

      logger.info("Loaded email templates", {
        loaded: this.templates.size,
        total: templateFiles.length,
      });

      // Check if critical templates are missing
      const missingCriticalTemplates = criticalTemplates.filter(
        (template) => !this.templates.has(path.basename(template, ".html"))
      );

      if (missingCriticalTemplates.length > 0) {
        const error = new Error(
          `Critical email templates failed to load: ${missingCriticalTemplates.join(
            ", "
          )}`
        );
        error.missingTemplates = missingCriticalTemplates;
        throw error;
      }

      // Warn if non-critical templates failed
      if (failedTemplates.length > 0) {
        logger.warn("Non-critical templates failed to load, using fallback versions", {
          failedTemplates,
        });
      }
    } catch (error) {
      logger.error("Failed to load email templates", {
        templatesDir,
        error,
      });
      throw error; // Re-throw to fail server startup
    }
  }

  /**
   * Render a template with the provided variables
   * @param {string} templateName - Name of the template to render
   * @param {Object} variables - Variables to substitute in the template
   * @returns {Promise<string>} Rendered HTML
   */
  async renderTemplate(templateName, variables = {}) {
    // Ensure service is initialized before rendering
    if (!this.initialized) {
      logger.debug("Template manager not initialized yet, initializing now...");
      await this.initialize();
    }

    let template = this.templates.get(templateName);

    if (!template) {
      logger.error("Template not found, using fallback", {
        templateName,
        availableTemplates: Array.from(this.templates.keys()),
      });
      template = this.getFallbackTemplate(templateName);
    } else {
      logger.debug("Template found", { templateName });
    }

    let rendered = template;

    try {
      Object.keys(variables).forEach((key) => {
        const regex = new RegExp(`{{${key}}}`, "g");
        rendered = rendered.replace(regex, variables[key] || "");
      });
    } catch (error) {
      logger.error("Error rendering template", {
        templateName,
        variableKeys: Object.keys(variables),
        error,
      });
    }

    return rendered;
  }

  /**
   * Get a fallback template when the HTML file is not available
   * @param {string} templateName - Name of the template
   * @returns {string} Fallback HTML template
   */
  getFallbackTemplate(templateName) {
    const baseTemplate = `
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{title}}</title>
        <style>
          body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
          .container { max-width: 600px; margin: 0 auto; background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
          .header { text-align: center; border-bottom: 2px solid #e9ecef; padding-bottom: 20px; margin-bottom: 30px; }
          .logo { font-size: 24px; font-weight: bold; color: #333; }
          .content { line-height: 1.6; color: #555; }
          .button { display: inline-block; background-color: #007bff; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; margin: 20px 0; }
          .footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #e9ecef; text-align: center; font-size: 12px; color: #6c757d; }
        </style>
      </head>
      <body>
        <div class="container">
          <div class="header">
            <div class="logo">Village Share</div>
          </div>
          <div class="content">
            {{content}}
          </div>
          <div class="footer">
            <p>This email was sent from Village Share. If you have any questions, please contact support.</p>
          </div>
        </div>
      </body>
      </html>
    `;

    const templates = {
      conditionCheckReminderToUser: baseTemplate.replace(
        "{{content}}",
        `
        <h2>{{title}}</h2>
        <p>{{message}}</p>
        <p><strong>Rental Item:</strong> {{itemName}}</p>
        <p><strong>Deadline:</strong> {{deadline}}</p>
        <p>Please complete this condition check as soon as possible to ensure proper documentation.</p>
      `
      ),

      rentalConfirmationToUser: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{recipientName}},</p>
        <h2>{{title}}</h2>
        <p>{{message}}</p>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
        <p>Thank you for using Village Share!</p>
      `
      ),

      emailVerificationToUser: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{recipientName}},</p>
        <h2>Verify Your Email Address</h2>
        <p>Thank you for registering with Village Share! Please verify your email address by clicking the button below.</p>
        <p><a href="{{verificationUrl}}" class="button">Verify Email Address</a></p>
        <p>If the button doesn't work, copy and paste this link into your browser: {{verificationUrl}}</p>
        <p><strong>This link will expire in 24 hours.</strong></p>
      `
      ),

      passwordResetToUser: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{recipientName}},</p>
        <h2>Reset Your Password</h2>
        <p>We received a request to reset the password for your Village Share account. Click the button below to choose a new password.</p>
        <p><a href="{{resetUrl}}" class="button">Reset Password</a></p>
        <p>If the button doesn't work, copy and paste this link into your browser: {{resetUrl}}</p>
        <p><strong>This link will expire in 1 hour.</strong></p>
        <p>If you didn't request this, you can safely ignore this email.</p>
      `
      ),

      passwordChangedToUser: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{recipientName}},</p>
        <h2>Your Password Has Been Changed</h2>
        <p>This is a confirmation that the password for your Village Share account ({{email}}) has been successfully changed.</p>
        <p><strong>Changed on:</strong> {{timestamp}}</p>
        <p>For your security, all existing sessions have been logged out.</p>
        <p><strong>Didn't change your password?</strong> If you did not make this change, please contact our support team immediately.</p>
      `
      ),

      rentalRequestToOwner: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{ownerName}},</p>
        <h2>New Rental Request for {{itemName}}</h2>
        <p>{{renterName}} would like to rent your item.</p>
        <p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
        <p><strong>Total Amount:</strong> \${{totalAmount}}</p>
        <p><strong>Your Earnings:</strong> \${{payoutAmount}}</p>
        <p><strong>Delivery Method:</strong> {{deliveryMethod}}</p>
        <p><strong>Intended Use:</strong> {{intendedUse}}</p>
        <p><a href="{{approveUrl}}" class="button">Review & Respond</a></p>
        <p>Please respond to this request within 24 hours.</p>
      `
      ),

      rentalRequestConfirmationToRenter: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{renterName}},</p>
        <h2>Your Rental Request Has Been Submitted!</h2>
        <p>Your request to rent <strong>{{itemName}}</strong> has been sent to the owner.</p>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
        <p><strong>Delivery Method:</strong> {{deliveryMethod}}</p>
        <p><strong>Total Amount:</strong> \${{totalAmount}}</p>
        <p>{{paymentMessage}}</p>
        <p>You'll receive an email notification once the owner responds to your request.</p>
        <p><a href="{{viewRentalsUrl}}" class="button">View My Rentals</a></p>
      `
      ),

      rentalCancellationConfirmationToUser: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{recipientName}},</p>
        <h2>Rental Cancelled Successfully</h2>
        <p>This confirms that your rental for <strong>{{itemName}}</strong> has been cancelled.</p>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Start Date:</strong> {{startDate}}</p>
        <p><strong>End Date:</strong> {{endDate}}</p>
        <p><strong>Cancelled On:</strong> {{cancelledAt}}</p>
        {{refundSection}}
      `
      ),

      rentalCancellationNotificationToUser: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{recipientName}},</p>
        <h2>Rental Cancellation Notice</h2>
        <p>{{cancellationMessage}}</p>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Start Date:</strong> {{startDate}}</p>
        <p><strong>End Date:</strong> {{endDate}}</p>
        <p><strong>Cancelled On:</strong> {{cancelledAt}}</p>
        {{additionalInfo}}
        <p>If you have any questions or concerns, please reach out to our support team.</p>
      `
      ),

      payoutReceivedToOwner: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{ownerName}},</p>
        <h2 style="color: #28a745;">Earnings Received: \${{payoutAmount}}</h2>
        <p>Great news! Your earnings from the rental of <strong>{{itemName}}</strong> have been transferred to your account.</p>
        <h3>Rental Details</h3>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
        <p><strong>Transfer ID:</strong> {{stripeTransferId}}</p>
        <h3>Earnings Breakdown</h3>
        <p><strong>Rental Amount:</strong> \${{totalAmount}}</p>
        <p><strong>Community Upkeep Fee (10%):</strong> -\${{platformFee}}</p>
        <p style="font-size: 18px; color: #28a745;"><strong>Your Earnings:</strong> \${{payoutAmount}}</p>
        <p>Funds are typically available in your bank account within 2-3 business days.</p>
        <p><a href="{{earningsDashboardUrl}}" class="button">View Earnings Dashboard</a></p>
        <p>Thank you for being a valued member of the Village Share community!</p>
      `
      ),

      rentalDeclinedToRenter: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{renterName}},</p>
        <h2>Rental Request Declined</h2>
        <p>Thank you for your interest in renting <strong>{{itemName}}</strong>. Unfortunately, the owner is unable to accept your rental request at this time.</p>
        <h3>Request Details</h3>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Start Date:</strong> {{startDate}}</p>
        <p><strong>End Date:</strong> {{endDate}}</p>
        <p><strong>Delivery Method:</strong> {{deliveryMethod}}</p>
        {{ownerMessage}}
        <div class="info-box">
          <p><strong>What happens next?</strong></p>
          <p>{{paymentMessage}}</p>
          <p>We encourage you to explore other similar items available for rent on Village Share. There are many great options waiting for you!</p>
        </div>
        <p style="text-align: center;"><a href="{{browseItemsUrl}}" class="button">Browse Available Items</a></p>
        <p>If you have any questions or concerns, please don't hesitate to contact our support team.</p>
      `
      ),

      rentalApprovalConfirmationToOwner: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{ownerName}},</p>
        <h2>You've Approved the Rental Request!</h2>
        <p>You've successfully approved the rental request for <strong>{{itemName}}</strong>.</p>
        <h3>Rental Details</h3>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Renter:</strong> {{renterName}}</p>
        <p><strong>Start Date:</strong> {{startDate}}</p>
        <p><strong>End Date:</strong> {{endDate}}</p>
        <p><strong>Your Earnings:</strong> \${{payoutAmount}}</p>
        {{stripeSection}}
        <h3>What's Next?</h3>
        <ul>
          <li>Coordinate with the renter on pickup details</li>
          <li>Take photos of the item's condition before handoff</li>
          <li>Provide any care instructions or usage tips</li>
        </ul>
        <p><a href="{{rentalDetailsUrl}}" class="button">View Rental Details</a></p>
      `
      ),

      rentalCompletionThankYouToRenter: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{renterName}},</p>
        <h2>Thank You for Returning On Time!</h2>
        <p>You've successfully returned <strong>{{itemName}}</strong> on time. On-time returns like yours help build trust in the Village Share community!</p>
        <h3>Rental Summary</h3>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
        <p><strong>Returned On:</strong> {{returnedDate}}</p>
        {{reviewSection}}
        <p><a href="{{browseItemsUrl}}" class="button">Browse Available Items</a></p>
      `
      ),

      rentalCompletionCongratsToOwner: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{ownerName}},</p>
        <h2>Congratulations on Completing a Rental!</h2>
        <p><strong>{{itemName}}</strong> has been successfully returned on time. Great job!</p>
        <h3>Rental Summary</h3>
        <p><strong>Item:</strong> {{itemName}}</p>
        <p><strong>Renter:</strong> {{renterName}}</p>
        <p><strong>Rental Period:</strong> {{startDate}} to {{endDate}}</p>
        {{earningsSection}}
        {{stripeSection}}
        <p><a href="{{owningUrl}}" class="button">View My Listings</a></p>
      `
      ),

      feedbackConfirmationToUser: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{userName}},</p>
        <h2>Thank You for Your Feedback!</h2>
        <p>We've received your feedback and our team will review it carefully.</p>
        <div style="background-color: #f8f9fa; border-left: 4px solid #007bff; padding: 15px; margin: 20px 0; font-style: italic;">
          {{feedbackText}}
        </div>
        <p><strong>Submitted:</strong> {{submittedAt}}</p>
        <p>Your input helps us improve Village Share for everyone. We take all feedback seriously and use it to make the platform better.</p>
        <p>If your feedback requires a response, our team will reach out to you directly.</p>
      `
      ),

      feedbackNotificationToAdmin: baseTemplate.replace(
        "{{content}}",
        `
        <h2>New Feedback Received</h2>
        <p><strong>From:</strong> {{userName}} ({{userEmail}})</p>
        <p><strong>User ID:</strong> {{userId}}</p>
        <p><strong>Submitted:</strong> {{submittedAt}}</p>
        <h3>Feedback Content</h3>
        <div style="background-color: #e7f3ff; border-left: 4px solid #007bff; padding: 20px; margin: 20px 0;">
          {{feedbackText}}
        </div>
        <h3>Technical Context</h3>
        <p><strong>Feedback ID:</strong> {{feedbackId}}</p>
        <p><strong>Page URL:</strong> {{url}}</p>
        <p><strong>User Agent:</strong> {{userAgent}}</p>
        <p>Please review this feedback and take appropriate action if needed.</p>
      `
      ),

      paymentDeclinedToRenter: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{renterFirstName}},</p>
        <h2>Payment Issue with Your Rental Request</h2>
        <p>The owner tried to approve your rental for <strong>{{itemName}}</strong>, but there was an issue processing your payment.</p>
        <h3>What Happened</h3>
        <p>{{declineReason}}</p>
        <div class="info-box">
          <p><strong>What You Can Do</strong></p>
          <p>Please update your payment method so the owner can complete the approval of your rental request.</p>
        </div>
        <p>Once you update your payment method, the owner will be notified and can try to approve your rental again.</p>
      `
      ),

      paymentMethodUpdatedToOwner: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{ownerFirstName}},</p>
        <h2>Payment Method Updated</h2>
        <p>The renter has updated their payment method for the rental of <strong>{{itemName}}</strong>.</p>
        <div class="info-box">
          <p><strong>Ready to Approve</strong></p>
          <p>You can now try approving the rental request again. The renter's new payment method will be charged when you approve.</p>
        </div>
        <p style="text-align: center;"><a href="{{approvalUrl}}" class="button">Review & Approve Rental</a></p>
      `
      ),

      userBannedNotification: baseTemplate.replace(
        "{{content}}",
        `
        <p>Hi {{userName}},</p>
        <h2>Your Account Has Been Suspended</h2>
        <p>Your Village Share account has been suspended by our moderation team.</p>
        <div style="background-color: #f8d7da; border-left: 4px solid #dc3545; padding: 20px; margin: 20px 0;">
          <p><strong>Reason for Suspension:</strong></p>
          <p>{{banReason}}</p>
        </div>
        <p>You have been logged out of all devices and cannot log in to your account.</p>
        <p>If you believe this suspension was made in error, please contact <a href="mailto:{{supportEmail}}">{{supportEmail}}</a>.</p>
      `
      ),
    };

    return (
      templates[templateName] ||
      baseTemplate.replace(
        "{{content}}",
        `
      <h2>{{title}}</h2>
      <p>{{message}}</p>
    `
      )
    );
  }
}

module.exports = TemplateManager;
