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

/**
 * RentalFlowEmailService handles rental lifecycle flow emails
 * This service is responsible for:
 * - Sending rental request notifications to owners
 * - Sending rental request confirmations to renters
 * - Sending rental approval confirmations to owners
 * - Sending rental declined notifications to renters
 * - Sending rental confirmation emails to renters and owners
 * - Sending rental cancellation emails to both parties
 * - Sending rental completion emails to both parties
 * - Sending payout received notifications to owners
 */
class RentalFlowEmailService {
  constructor() {
    this.emailClient = new EmailClient();
    this.templateManager = new TemplateManager();
    this.initialized = false;
  }

  /**
   * Initialize the rental flow 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("Rental Flow Email Service initialized successfully");
  }

  /**
   * Send rental request email to owner
   * @param {Object} owner - Owner user object
   * @param {string} owner.email - Owner's email address
   * @param {string} owner.firstName - Owner's first name
   * @param {Object} renter - Renter user object
   * @param {string} renter.firstName - Renter's first name
   * @param {string} renter.lastName - Renter's last name
   * @param {Object} rental - Rental object with all details
   * @param {number} rental.id - Rental ID
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.totalAmount - Total rental amount
   * @param {string} rental.payoutAmount - Owner's payout amount
   * @param {string} rental.deliveryMethod - Delivery method
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendRentalRequestEmail(owner, renter, rental) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const approveUrl = `${frontendUrl}/owning?rentalId=${rental.id}`;

      const variables = {
        ownerName: owner.firstName,
        renterName:
          `${renter.firstName} ${renter.lastName}`.trim() || "A renter",
        itemName: rental.item?.name || "your item",
        startDate: rental.startDateTime
          ? new Date(rental.startDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        endDate: rental.endDateTime
          ? new Date(rental.endDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        totalAmount: rental.totalAmount
          ? parseFloat(rental.totalAmount).toFixed(2)
          : "0.00",
        payoutAmount: rental.payoutAmount
          ? parseFloat(rental.payoutAmount).toFixed(2)
          : "0.00",
        deliveryMethod: rental.deliveryMethod || "Not specified",
        intendedUse: rental.intendedUse || "Not specified",
        approveUrl: approveUrl,
      };

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

      return await this.emailClient.sendEmail(
        owner.email,
        `Rental Request for ${rental.item?.name || "Your Item"}`,
        htmlContent
      );
    } catch (error) {
      logger.error("Failed to send rental request email", { error });
      return { success: false, error: error.message };
    }
  }

  /**
   * Send rental request confirmation email to renter
   * @param {Object} renter - Renter user object
   * @param {string} renter.email - Renter's email address
   * @param {string} renter.firstName - Renter's first name
   * @param {Object} rental - Rental object with all details
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.totalAmount - Total rental amount
   * @param {string} rental.deliveryMethod - Delivery method
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendRentalRequestConfirmationEmail(renter, rental) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const viewRentalsUrl = `${frontendUrl}/renting`;

      // Determine payment message based on rental amount
      const totalAmount = parseFloat(rental.totalAmount) || 0;
      const paymentMessage =
        totalAmount > 0
          ? "The owner will review your request. You'll only be charged if they approve it."
          : "The owner will review your request and respond soon.";

      const variables = {
        renterName: renter.firstName || "there",
        itemName: rental.item?.name || "the item",
        startDate: rental.startDateTime
          ? new Date(rental.startDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        endDate: rental.endDateTime
          ? new Date(rental.endDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        totalAmount: totalAmount.toFixed(2),
        deliveryMethod: rental.deliveryMethod || "Not specified",
        paymentMessage: paymentMessage,
        viewRentalsUrl: viewRentalsUrl,
      };

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

      return await this.emailClient.sendEmail(
        renter.email,
        `Rental Request Submitted - ${rental.item?.name || "Item"}`,
        htmlContent
      );
    } catch (error) {
      logger.error("Failed to send rental request confirmation email", { error });
      return { success: false, error: error.message };
    }
  }

  /**
   * Send rental approval confirmation email to owner
   * @param {Object} owner - Owner user object
   * @param {string} owner.email - Owner's email address
   * @param {string} owner.firstName - Owner's first name
   * @param {string} owner.stripeConnectedAccountId - Owner's Stripe account ID
   * @param {Object} renter - Renter user object
   * @param {string} renter.firstName - Renter's first name
   * @param {string} renter.lastName - Renter's last name
   * @param {Object} rental - Rental object with all details
   * @param {number} rental.id - Rental ID
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.deliveryMethod - Delivery method
   * @param {string} rental.totalAmount - Total rental amount
   * @param {string} rental.payoutAmount - Owner's payout amount
   * @param {string} rental.platformFee - Platform fee amount
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendRentalApprovalConfirmationEmail(owner, renter, rental) {
    if (!this.initialized) {
      await this.initialize();
    }

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

      // Determine if Stripe setup is needed
      const hasStripeAccount = !!owner.stripeConnectedAccountId;
      const totalAmount = parseFloat(rental.totalAmount) || 0;
      const payoutAmount = parseFloat(rental.payoutAmount) || 0;
      const platformFee = parseFloat(rental.platformFee) || 0;

      // Build payment message
      const isPaidRental = totalAmount > 0;
      let paymentMessage = "";
      if (isPaidRental) {
        paymentMessage = "their payment has been processed successfully.";
      } else {
        paymentMessage = "this is a free rental (no payment required).";
      }

      // Build earnings section (only for paid rentals)
      let earningsSection = "";
      if (isPaidRental) {
        earningsSection = `
            <h2>Your Earnings</h2>
            <table class="info-table">
                <tr>
                    <th>Total Rental Amount</th>
                    <td>$${totalAmount.toFixed(2)}</td>
                </tr>
                <tr>
                    <th>Community Upkeep Fee (10%)</th>
                    <td>-$${platformFee.toFixed(2)}</td>
                </tr>
                <tr>
                    <th>Your Payout</th>
                    <td class="highlight">$${payoutAmount.toFixed(2)}</td>
                </tr>
            </table>
      `;
      }

      // Build conditional Stripe section based on Stripe status
      let stripeSection = "";
      if (!hasStripeAccount && isPaidRental) {
        // Only show Stripe setup reminder for paid rentals
        stripeSection = `
            <div class="warning-box">
                <p><strong>⚠️ Action Required: Set Up Your Earnings Account</strong></p>
                <p>To receive your payout of <strong>$${payoutAmount.toFixed(
                  2
                )}</strong> when this rental completes, you need to set up your earnings account.</p>
            </div>
            <h2>Set Up Earnings to Get Paid</h2>
            <div class="info-box">
                <p><strong>Why set up now?</strong></p>
                <ul>
                    <li><strong>Automatic payouts</strong> when rentals complete</li>
                    <li><strong>Secure transfers</strong> directly to your bank account</li>
                    <li><strong>Track all earnings</strong> in one dashboard</li>
                    <li><strong>Fast deposits</strong> (typically 2-7 business days)</li>
                </ul>
                <p>Setup only takes about 5 minutes and you only need to do it once.</p>
            </div>
            <p style="text-align: center;">
                <a href="${frontendUrl}/earnings" class="button">Set Up Earnings Account Now</a>
            </p>
            <p style="text-align: center; font-size: 14px; color: #856404;">
                <strong>Important:</strong> Without earnings setup, you won't receive payouts automatically when rentals complete.
            </p>
      `;
      } else if (hasStripeAccount && isPaidRental) {
        stripeSection = `
            <div class="success-box">
                <p><strong>✓ Earnings Account Active</strong></p>
                <p>Your earnings account is set up. You'll automatically receive $${payoutAmount.toFixed(
                  2
                )} when this rental completes.</p>
                <p><a href="${frontendUrl}/earnings" style="color: #155724; text-decoration: underline;">View your earnings dashboard →</a></p>
            </div>
      `;
      }

      // Format delivery method for display
      const deliveryMethodDisplay =
        rental.deliveryMethod === "delivery" ? "Delivery" : "Pickup";

      const variables = {
        ownerName: owner.firstName || "there",
        itemName: rental.item?.name || "your item",
        renterName:
          `${renter.firstName} ${renter.lastName}`.trim() || "The renter",
        startDate: rental.startDateTime
          ? new Date(rental.startDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        endDate: rental.endDateTime
          ? new Date(rental.endDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        deliveryMethod: deliveryMethodDisplay,
        paymentMessage: paymentMessage,
        earningsSection: earningsSection,
        stripeSection: stripeSection,
        rentalDetailsUrl: `${frontendUrl}/owning?rentalId=${rental.id}`,
      };

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

      const subject = `Rental Approved - ${rental.item?.name || "Your Item"}`;

      return await this.emailClient.sendEmail(
        owner.email,
        subject,
        htmlContent
      );
    } catch (error) {
      logger.error("Failed to send rental approval confirmation email", { error });
      return { success: false, error: error.message };
    }
  }

  /**
   * Send rental declined email to renter
   * @param {Object} renter - Renter user object
   * @param {string} renter.email - Renter's email address
   * @param {string} renter.firstName - Renter's first name
   * @param {Object} rental - Rental object with all details
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.totalAmount - Total rental amount
   * @param {string} rental.payoutAmount - Owner's payout amount
   * @param {string} rental.deliveryMethod - Delivery method
   * @param {string|null} declineReason - Reason for declining rental (optional)
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendRentalDeclinedEmail(renter, rental, declineReason) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const browseItemsUrl = `${frontendUrl}/`;

      // Determine payment message based on rental amount
      const totalAmount = parseFloat(rental.totalAmount) || 0;
      const paymentMessage =
        totalAmount > 0
          ? "Since your request was declined before payment was processed, you will not be charged."
          : "No payment was required for this rental request.";

      // Build owner message section if decline reason provided
      const ownerMessage = declineReason
        ? `
        <div class="notice-box">
          <p><strong>Message from the owner:</strong></p>
          <p>${declineReason}</p>
        </div>
      `
        : "";

      const variables = {
        renterName: renter.firstName || "there",
        itemName: rental.item?.name || "the item",
        startDate: rental.startDateTime
          ? new Date(rental.startDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        endDate: rental.endDateTime
          ? new Date(rental.endDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        deliveryMethod: rental.deliveryMethod || "Not specified",
        paymentMessage: paymentMessage,
        ownerMessage: ownerMessage,
        browseItemsUrl: browseItemsUrl,
        payoutAmount: rental.payoutAmount
          ? parseFloat(rental.payoutAmount).toFixed(2)
          : "0.00",
        totalAmount: totalAmount.toFixed(2),
      };

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

      return await this.emailClient.sendEmail(
        renter.email,
        `Rental Request Declined - ${rental.item?.name || "Item"}`,
        htmlContent
      );
    } catch (error) {
      logger.error("Failed to send rental declined email", { error });
      return { success: false, error: error.message };
    }
  }

  /**
   * Send rental confirmation email with payment receipt (if applicable)
   * @param {string} userEmail - User's email address
   * @param {Object} notification - Notification object
   * @param {string} notification.title - Notification title
   * @param {string} notification.message - Notification message
   * @param {Object} rental - Rental object with all rental details
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.totalAmount - Total rental amount
   * @param {string} rental.paymentStatus - Payment status
   * @param {string} rental.paymentMethodBrand - Payment method brand
   * @param {string} rental.paymentMethodLast4 - Last 4 digits of payment method
   * @param {string} rental.stripePaymentIntentId - Stripe payment intent ID
   * @param {string} rental.chargedAt - Payment charge timestamp
   * @param {string|null} recipientName - Recipient's name
   * @param {boolean} isRenter - Whether recipient is the renter (to show payment receipt)
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendRentalConfirmation(
    userEmail,
    notification,
    rental,
    recipientName = null,
    isRenter = false
  ) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const itemName = rental?.item?.name || "Unknown Item";

      const variables = {
        recipientName: recipientName || "there",
        title: notification.title,
        message: notification.message,
        itemName: itemName,
        startDate: rental?.startDateTime
          ? new Date(rental.startDateTime).toLocaleDateString()
          : "Not specified",
        endDate: rental?.endDateTime
          ? new Date(rental.endDateTime).toLocaleDateString()
          : "Not specified",
        isRenter: isRenter,
      };

      // Add payment information if this is for the renter and rental has payment info
      let paymentSection = "";
      if (isRenter) {
        const totalAmount = parseFloat(rental.totalAmount) || 0;
        const isPaidRental = totalAmount > 0 && rental.paymentStatus === "paid";

        if (isPaidRental) {
          // Format payment method display
          let paymentMethodDisplay = "Payment method on file";
          if (rental.paymentMethodBrand && rental.paymentMethodLast4) {
            const brandCapitalized =
              rental.paymentMethodBrand.charAt(0).toUpperCase() +
              rental.paymentMethodBrand.slice(1);
            paymentMethodDisplay = `${brandCapitalized} ending in ${rental.paymentMethodLast4}`;
          }

          const chargedAtFormatted = rental.chargedAt
            ? new Date(rental.chargedAt).toLocaleString("en-US", {
                dateStyle: "medium",
                timeStyle: "short",
              })
            : new Date().toLocaleString("en-US", {
                dateStyle: "medium",
                timeStyle: "short",
              });

          // Build payment receipt section HTML
          paymentSection = `
            <h2>Payment Receipt</h2>
            <div class="success-box">
                <div class="icon">💳</div>
                <p><strong>Payment Successful</strong></p>
                <p>Your payment has been processed. This email serves as your receipt.</p>
            </div>
            <table class="info-table">
                <tr>
                    <th>Amount Charged</th>
                    <td><strong>$${totalAmount.toFixed(2)}</strong></td>
                </tr>
                <tr>
                    <th>Payment Method</th>
                    <td>${paymentMethodDisplay}</td>
                </tr>
                <tr>
                    <th>Transaction ID</th>
                    <td style="font-family: monospace; font-size: 12px;">${
                      rental.stripePaymentIntentId || "N/A"
                    }</td>
                </tr>
                <tr>
                    <th>Transaction Date</th>
                    <td>${chargedAtFormatted}</td>
                </tr>
            </table>
            <p style="font-size: 13px; color: #6c757d; margin-top: 10px;">
                <strong>Note:</strong> Keep this email for your records. You can use the transaction ID above if you need to contact support about this payment.
            </p>
        `;
        } else if (totalAmount === 0) {
          // Free rental message
          paymentSection = `
            <div class="success-box">
                <p><strong>No Payment Required:</strong> This is a free rental.</p>
            </div>
        `;
        }
      }

      variables.paymentSection = paymentSection;

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

      // Use clear, transactional subject line with item name
      const subject = `Rental Confirmation - ${itemName}`;

      return await this.emailClient.sendEmail(userEmail, subject, htmlContent);
    } catch (error) {
      logger.error("Failed to send rental confirmation", { error });
      return { success: false, error: error.message };
    }
  }

  /**
   * Send rental confirmation emails to both owner and renter
   * @param {Object} owner - Owner user object
   * @param {string} owner.email - Owner's email address
   * @param {string} owner.firstName - Owner's first name
   * @param {Object} renter - Renter user object
   * @param {string} renter.email - Renter's email address
   * @param {string} renter.firstName - Renter's first name
   * @param {Object} rental - Rental object with all details
   * @param {number} rental.id - Rental ID
   * @param {number} rental.ownerId - Owner's user ID
   * @param {number} rental.renterId - Renter's user ID
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @returns {Promise<{ownerEmailSent: boolean, renterEmailSent: boolean}>}
   */
  async sendRentalConfirmationEmails(owner, renter, rental) {
    if (!this.initialized) {
      await this.initialize();
    }

    const results = {
      ownerEmailSent: false,
      renterEmailSent: false,
    };

    try {
      // Create notification data for owner
      const ownerNotification = {
        type: "rental_confirmed",
        title: "Rental Confirmed",
        message: `Your "${rental.item.name}" has been confirmed for rental.`,
        rentalId: rental.id,
        userId: rental.ownerId,
        metadata: { rentalStart: rental.startDateTime },
      };

      // Create notification data for renter
      const renterNotification = {
        type: "rental_confirmed",
        title: "Rental Confirmed",
        message: `Your rental of "${rental.item.name}" has been confirmed.`,
        rentalId: rental.id,
        userId: rental.renterId,
        metadata: { rentalStart: rental.startDateTime },
      };

      // Send email to owner - independent error handling
      if (owner?.email) {
        try {
          const ownerResult = await this.sendRentalConfirmation(
            owner.email,
            ownerNotification,
            rental,
            owner.firstName,
            false // isRenter = false for owner
          );
          if (ownerResult.success) {
            logger.info("Rental confirmation email sent to owner", { email: owner.email });
            results.ownerEmailSent = true;
          } else {
            logger.error("Failed to send rental confirmation email to owner", {
              email: owner.email,
              error: ownerResult.error,
            });
          }
        } catch (error) {
          logger.error("Failed to send rental confirmation email to owner", {
            email: owner.email,
            error,
          });
        }
      }

      // Send email to renter - independent error handling
      if (renter?.email) {
        try {
          const renterResult = await this.sendRentalConfirmation(
            renter.email,
            renterNotification,
            rental,
            renter.firstName,
            true // isRenter = true for renter (enables payment receipt)
          );
          if (renterResult.success) {
            logger.info("Rental confirmation email sent to renter", { email: renter.email });
            results.renterEmailSent = true;
          } else {
            logger.error("Failed to send rental confirmation email to renter", {
              email: renter.email,
              error: renterResult.error,
            });
          }
        } catch (error) {
          logger.error("Failed to send rental confirmation email to renter", {
            email: renter.email,
            error,
          });
        }
      }
    } catch (error) {
      logger.error("Error fetching user data for rental confirmation emails", { error });
    }

    return results;
  }

  /**
   * Send rental cancellation emails to both parties
   * @param {Object} owner - Owner user object
   * @param {string} owner.email - Owner's email address
   * @param {string} owner.firstName - Owner's first name
   * @param {Object} renter - Renter user object
   * @param {string} renter.email - Renter's email address
   * @param {string} renter.firstName - Renter's first name
   * @param {Object} rental - Rental object with all details
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.cancelledBy - Who cancelled ('owner' or 'renter')
   * @param {string} rental.cancelledAt - Cancellation timestamp
   * @param {string} rental.totalAmount - Total rental amount
   * @param {Object} refundInfo - Refund information
   * @param {number} refundInfo.amount - Refund amount
   * @param {number} refundInfo.percentage - Refund percentage (0-1)
   * @param {string} refundInfo.reason - Refund reason description
   * @returns {Promise<{confirmationEmailSent: boolean, notificationEmailSent: boolean}>}
   */
  async sendRentalCancellationEmails(owner, renter, rental, refundInfo) {
    if (!this.initialized) {
      await this.initialize();
    }

    const results = {
      confirmationEmailSent: false,
      notificationEmailSent: false,
    };

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const browseUrl = `${frontendUrl}/`;

      const cancelledBy = rental.cancelledBy;
      const itemName = rental.item?.name || "the item";
      const startDate = rental.startDateTime
        ? new Date(rental.startDateTime).toLocaleString("en-US", {
            dateStyle: "medium",
            timeStyle: "short",
          })
        : "Not specified";
      const endDate = rental.endDateTime
        ? new Date(rental.endDateTime).toLocaleString("en-US", {
            dateStyle: "medium",
            timeStyle: "short",
          })
        : "Not specified";
      const cancelledAt = rental.cancelledAt
        ? new Date(rental.cancelledAt).toLocaleString("en-US", {
            dateStyle: "medium",
            timeStyle: "short",
          })
        : "Not specified";

      // Determine who gets confirmation and who gets notification
      let confirmationRecipient, notificationRecipient;
      let confirmationRecipientName, notificationRecipientName;
      let cancellationMessage, additionalInfo;

      if (cancelledBy === "owner") {
        // Owner cancelled: owner gets confirmation, renter gets notification
        confirmationRecipient = owner.email;
        confirmationRecipientName = owner.firstName || "there";
        notificationRecipient = renter.email;
        notificationRecipientName = renter.firstName || "there";

        cancellationMessage = `The owner has cancelled the rental for <strong>${itemName}</strong>. We apologize for any inconvenience this may cause.`;

        // Only show refund info if rental had a cost
        if (rental.totalAmount > 0) {
          additionalInfo = `
            <div class="info-box">
              <p><strong>Full Refund Processed</strong></p>
              <p>You will receive a full refund of $${refundInfo.amount.toFixed(
                2
              )}. The refund will appear in your account within 5-10 business days.</p>
            </div>
            <div style="text-align: center">
              <a href="${browseUrl}" class="button">Browse Other Items</a>
            </div>
          `;
        } else {
          additionalInfo = `
            <div class="info-box">
              <p>This rental has been cancelled by the owner. We apologize for any inconvenience.</p>
            </div>
            <div style="text-align: center">
              <a href="${browseUrl}" class="button">Browse Other Items</a>
            </div>
          `;
        }
      } else {
        // Renter cancelled: renter gets confirmation, owner gets notification
        confirmationRecipient = renter.email;
        confirmationRecipientName = renter.firstName || "there";
        notificationRecipient = owner.email;
        notificationRecipientName = owner.firstName || "there";

        cancellationMessage = `The renter has cancelled their rental for <strong>${itemName}</strong>.`;
        additionalInfo = `
          <div class="info-box">
            <p><strong>Your item is now available</strong></p>
            <p>Your item is now available for other renters to book for these dates.</p>
          </div>
        `;
      }

      // Build refund section for confirmation email (only for paid rentals)
      let refundSection = "";
      if (rental.totalAmount > 0) {
        if (refundInfo.amount > 0) {
          const refundPercentage = (refundInfo.percentage * 100).toFixed(0);
          refundSection = `
            <h2>Refund Information</h2>
            <div class="refund-amount">$${refundInfo.amount.toFixed(2)}</div>
            <div class="info-box">
              <p><strong>Refund Amount:</strong> $${refundInfo.amount.toFixed(
                2
              )} (${refundPercentage}% of total)</p>
              <p><strong>Reason:</strong> ${refundInfo.reason}</p>
              <p><strong>Processing Time:</strong> Refunds typically appear within 5-10 business days.</p>
            </div>
          `;
        } else {
          refundSection = `
            <h2>Refund Information</h2>
            <div class="warning-box">
              <p><strong>No Refund Available</strong></p>
              <p>${refundInfo.reason}</p>
            </div>
          `;
        }
      }

      // Send confirmation email to canceller
      try {
        const confirmationVariables = {
          recipientName: confirmationRecipientName,
          itemName: itemName,
          startDate: startDate,
          endDate: endDate,
          cancelledAt: cancelledAt,
          refundSection: refundSection,
        };

        const confirmationHtml = await this.templateManager.renderTemplate(
          "rentalCancellationConfirmationToUser",
          confirmationVariables
        );

        const confirmationResult = await this.emailClient.sendEmail(
          confirmationRecipient,
          `Cancellation Confirmed - ${itemName}`,
          confirmationHtml
        );

        if (confirmationResult.success) {
          logger.info("Cancellation confirmation email sent", {
            cancelledBy,
            email: confirmationRecipient,
          });
          results.confirmationEmailSent = true;
        }
      } catch (error) {
        logger.error("Failed to send cancellation confirmation email", {
          cancelledBy,
          error,
        });
      }

      // Send notification email to other party
      try {
        const notificationVariables = {
          recipientName: notificationRecipientName,
          itemName: itemName,
          startDate: startDate,
          endDate: endDate,
          cancelledAt: cancelledAt,
          cancellationMessage: cancellationMessage,
          additionalInfo: additionalInfo,
        };

        const notificationHtml = await this.templateManager.renderTemplate(
          "rentalCancellationNotificationToUser",
          notificationVariables
        );

        const notificationResult = await this.emailClient.sendEmail(
          notificationRecipient,
          `Rental Cancelled - ${itemName}`,
          notificationHtml
        );

        if (notificationResult.success) {
          logger.info("Cancellation notification email sent", {
            recipientType: cancelledBy === "owner" ? "renter" : "owner",
            email: notificationRecipient,
          });
          results.notificationEmailSent = true;
        }
      } catch (error) {
        logger.error("Failed to send cancellation notification email", { error });
      }
    } catch (error) {
      logger.error("Error sending cancellation emails", { error });
    }

    return results;
  }

  /**
   * Send rental completion emails to both owner and renter
   * @param {Object} owner - Owner user object
   * @param {string} owner.email - Owner's email address
   * @param {string} owner.firstName - Owner's first name
   * @param {string} owner.lastName - Owner's last name
   * @param {string} owner.stripeConnectedAccountId - Owner's Stripe account ID
   * @param {Object} renter - Renter user object
   * @param {string} renter.email - Renter's email address
   * @param {string} renter.firstName - Renter's first name
   * @param {string} renter.lastName - Renter's last name
   * @param {Object} rental - Rental object with all details
   * @param {number} rental.id - Rental ID
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.actualReturnDateTime - Actual return timestamp
   * @param {string} rental.itemReviewSubmittedAt - Review submission timestamp
   * @param {string} rental.totalAmount - Total rental amount
   * @param {string} rental.payoutAmount - Owner's payout amount
   * @param {string} rental.platformFee - Platform fee amount
   * @returns {Promise<{renterEmailSent: boolean, ownerEmailSent: boolean}>}
   */
  async sendRentalCompletionEmails(owner, renter, rental) {
    if (!this.initialized) {
      await this.initialize();
    }

    const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
    const results = {
      renterEmailSent: false,
      ownerEmailSent: false,
    };

    try {
      // Format dates
      const startDate = rental.startDateTime
        ? new Date(rental.startDateTime).toLocaleString("en-US", {
            dateStyle: "medium",
            timeStyle: "short",
          })
        : "Not specified";
      const endDate = rental.endDateTime
        ? new Date(rental.endDateTime).toLocaleString("en-US", {
            dateStyle: "medium",
            timeStyle: "short",
          })
        : "Not specified";
      const returnedDate = rental.actualReturnDateTime
        ? new Date(rental.actualReturnDateTime).toLocaleString("en-US", {
            dateStyle: "medium",
            timeStyle: "short",
          })
        : endDate;

      // Check if renter has already submitted a review
      const hasReviewed = !!rental.itemReviewSubmittedAt;

      // Build review section for renter email
      let reviewSection = "";
      if (!hasReviewed) {
        reviewSection = `
            <h2>Share Your Experience</h2>
            <div class="info-box">
                <p><strong>Help the community by leaving a review!</strong></p>
                <p>Your feedback helps other renters make informed decisions and supports quality listings on Village Share.</p>
                <ul>
                    <li>How was the item's condition?</li>
                    <li>Was the owner responsive and helpful?</li>
                    <li>Would you rent this item again?</li>
                </ul>
            </div>
            <p style="text-align: center;">
                <a href="${frontendUrl}/renting?rentalId=${rental.id}&action=review" class="button">Leave a Review</a>
            </p>
        `;
      } else {
        reviewSection = `
            <div class="success-box">
                <p><strong>✓ Thank You for Your Review!</strong></p>
                <p>Your feedback has been submitted and helps strengthen the Village Share community.</p>
            </div>
        `;
      }

      // Send email to renter
      try {
        const renterVariables = {
          renterName: renter.firstName || "there",
          itemName: rental.item?.name || "the item",
          ownerName: owner.firstName || "the owner",
          startDate: startDate,
          endDate: endDate,
          returnedDate: returnedDate,
          reviewSection: reviewSection,
          browseItemsUrl: `${frontendUrl}/`,
        };

        const renterHtmlContent = await this.templateManager.renderTemplate(
          "rentalCompletionThankYouToRenter",
          renterVariables
        );

        const renterResult = await this.emailClient.sendEmail(
          renter.email,
          `Thank You for Returning "${rental.item?.name || "Item"}" On Time!`,
          renterHtmlContent
        );

        if (renterResult.success) {
          logger.info("Rental completion thank you email sent to renter", { email: renter.email });
          results.renterEmailSent = true;
        } else {
          logger.error("Failed to send rental completion email to renter", {
            email: renter.email,
            error: renterResult.error,
          });
        }
      } catch (emailError) {
        logger.error("Failed to send rental completion email to renter", {
          error: emailError.message,
          stack: emailError.stack,
          renterEmail: renter.email,
          rentalId: rental.id,
        });
      }

      // Prepare owner email
      const hasStripeAccount = !!owner.stripeConnectedAccountId;
      const totalAmount = parseFloat(rental.totalAmount) || 0;
      const payoutAmount = parseFloat(rental.payoutAmount) || 0;
      const platformFee = parseFloat(rental.platformFee) || 0;
      const isPaidRental = totalAmount > 0;

      // Build earnings section for owner (only for paid rentals)
      let earningsSection = "";
      if (isPaidRental) {
        earningsSection = `
            <h2>Your Earnings</h2>
            <table class="info-table">
                <tr>
                    <th>Total Rental Amount</th>
                    <td>$${totalAmount.toFixed(2)}</td>
                </tr>
                <tr>
                    <th>Community Upkeep Fee (10%)</th>
                    <td>-$${platformFee.toFixed(2)}</td>
                </tr>
                <tr>
                    <th>Your Payout</th>
                    <td class="highlight">$${payoutAmount.toFixed(2)}</td>
                </tr>
            </table>
            <p style="font-size: 14px; color: #6c757d;">
                Your earnings are transferred immediately when the rental is marked complete. Funds typically reach your bank within 2-7 business days.
            </p>
        `;
      }

      // Build Stripe section for owner
      let stripeSection = "";
      if (!hasStripeAccount && isPaidRental) {
        // Show Stripe setup reminder for paid rentals
        stripeSection = `
            <div class="warning-box">
                <p><strong>⚠️ Action Required: Set Up Your Earnings Account</strong></p>
                <p>To receive your payout of <strong>$${payoutAmount.toFixed(
                  2
                )}</strong>, you need to set up your earnings account.</p>
            </div>
            <h2>Set Up Earnings to Get Paid</h2>
            <div class="info-box">
                <p><strong>Why set up now?</strong></p>
                <ul>
                    <li><strong>Automatic payouts</strong> when the rental period ends</li>
                    <li><strong>Secure transfers</strong> directly to your bank account</li>
                    <li><strong>Track all earnings</strong> in one dashboard</li>
                    <li><strong>Fast deposits</strong> (typically 2-7 business days)</li>
                </ul>
                <p>Setup only takes about 5 minutes and you only need to do it once.</p>
            </div>
            <p style="text-align: center;">
                <a href="${frontendUrl}/earnings" class="button">Set Up Earnings Account Now</a>
            </p>
            <p style="text-align: center; font-size: 14px; color: #856404;">
                <strong>Important:</strong> Without earnings setup, you won't receive payouts automatically.
            </p>
        `;
      } else if (hasStripeAccount && isPaidRental) {
        stripeSection = `
            <div class="success-box">
                <p><strong>✓ Payout Initiated</strong></p>
                <p>Your earnings of <strong>$${payoutAmount.toFixed(
                  2
                )}</strong> have been transferred to your Stripe account.</p>
                <p style="font-size: 14px; margin-top: 10px;">Funds typically reach your bank within 2-7 business days.</p>
                <p><a href="${frontendUrl}/earnings" style="color: #155724; text-decoration: underline;">View your earnings dashboard →</a></p>
            </div>
        `;
      }

      // Send email to owner
      try {
        const ownerVariables = {
          ownerName: owner.firstName || "there",
          itemName: rental.item?.name || "your item",
          renterName:
            `${renter.firstName} ${renter.lastName}`.trim() || "The renter",
          startDate: startDate,
          endDate: endDate,
          returnedDate: returnedDate,
          earningsSection: earningsSection,
          stripeSection: stripeSection,
          owningUrl: `${frontendUrl}/owning`,
        };

        const ownerHtmlContent = await this.templateManager.renderTemplate(
          "rentalCompletionCongratsToOwner",
          ownerVariables
        );

        const ownerResult = await this.emailClient.sendEmail(
          owner.email,
          `Rental Complete - ${rental.item?.name || "Your Item"}`,
          ownerHtmlContent
        );

        if (ownerResult.success) {
          logger.info("Rental completion congratulations email sent to owner", { email: owner.email });
          results.ownerEmailSent = true;
        } else {
          logger.error("Failed to send rental completion email to owner", {
            email: owner.email,
            error: ownerResult.error,
          });
        }
      } catch (emailError) {
        logger.error("Failed to send rental completion email to owner", {
          error: emailError.message,
          stack: emailError.stack,
          ownerEmail: owner.email,
          rentalId: rental.id,
        });
      }
    } catch (error) {
      logger.error("Error sending rental completion emails", {
        error: error.message,
        stack: error.stack,
        rentalId: rental?.id,
      });
    }

    return results;
  }

  /**
   * Send payout received email to owner
   * @param {Object} owner - Owner user object
   * @param {string} owner.email - Owner's email address
   * @param {string} owner.firstName - Owner's first name
   * @param {Object} rental - Rental object with all details
   * @param {Object} rental.item - Item object
   * @param {string} rental.item.name - Item name
   * @param {string} rental.startDateTime - Rental start date
   * @param {string} rental.endDateTime - Rental end date
   * @param {string} rental.totalAmount - Total rental amount
   * @param {string} rental.platformFee - Platform fee amount
   * @param {string} rental.payoutAmount - Owner's payout amount
   * @param {string} rental.stripeTransferId - Stripe transfer ID
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendPayoutReceivedEmail(owner, rental) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
      const earningsDashboardUrl = `${frontendUrl}/earnings`;

      // Format currency values
      const totalAmount = parseFloat(rental.totalAmount) || 0;
      const platformFee = parseFloat(rental.platformFee) || 0;
      const payoutAmount = parseFloat(rental.payoutAmount) || 0;

      const variables = {
        ownerName: owner.firstName || "there",
        itemName: rental.item?.name || "your item",
        startDate: rental.startDateTime
          ? new Date(rental.startDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        endDate: rental.endDateTime
          ? new Date(rental.endDateTime).toLocaleString("en-US", {
              dateStyle: "medium",
              timeStyle: "short",
            })
          : "Not specified",
        totalAmount: totalAmount.toFixed(2),
        platformFee: platformFee.toFixed(2),
        payoutAmount: payoutAmount.toFixed(2),
        stripeTransferId: rental.stripeTransferId || "N/A",
        earningsDashboardUrl: earningsDashboardUrl,
      };

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

      return await this.emailClient.sendEmail(
        owner.email,
        `Earnings Received - $${payoutAmount.toFixed(2)} for ${
          rental.item?.name || "Your Item"
        }`,
        htmlContent
      );
    } catch (error) {
      logger.error("Failed to send payout received email", { error });
      return { success: false, error: error.message };
    }
  }

  /**
   * Send authentication required email to renter when 3DS verification is needed
   * This is sent when the owner approves a rental but the renter's bank requires
   * additional verification (3D Secure) to complete the payment.
   *
   * @param {string} email - Renter's email address
   * @param {Object} data - Email data
   * @param {string} data.renterName - Renter's first name
   * @param {string} data.itemName - Name of the item being rented
   * @param {string} data.ownerName - Owner's first name
   * @param {number} data.amount - Total rental amount
   * @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
   */
  async sendAuthenticationRequiredEmail(email, data) {
    if (!this.initialized) {
      await this.initialize();
    }

    try {
      const { renterName, itemName, ownerName, amount } = data;

      const variables = {
        renterName: renterName || "there",
        itemName: itemName || "the item",
        ownerName: ownerName || "The owner",
        amount: typeof amount === "number" ? amount.toFixed(2) : "0.00",
      };

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

      return await this.emailClient.sendEmail(
        email,
        `Action Required: Complete payment for ${itemName}`,
        htmlContent
      );
    } catch (error) {
      logger.error("Failed to send authentication required email", { error });
      return { success: false, error: error.message };
    }
  }
}

module.exports = RentalFlowEmailService;
