const { Rental, Item, ConditionCheck, User } = require("../models");
const LateReturnService = require("./lateReturnService");
const emailServices = require("./email");
const { isActive } = require("../utils/rentalStatus");

class DamageAssessmentService {
  /**
   * Process damage assessment and calculate fees
   * @param {string} rentalId - Rental ID
   * @param {Object} damageInfo - Damage assessment information
   * @param {string} userId - Owner reporting the damage
   * @returns {Object} - Updated rental with damage fees
   */
  static async processDamageAssessment(rentalId, damageInfo, userId) {
    const {
      description,
      canBeFixed,
      repairCost,
      needsReplacement,
      replacementCost,
      proofOfOwnership,
      actualReturnDateTime,
      imageFilenames = [],
    } = damageInfo;

    const rental = await Rental.findByPk(rentalId, {
      include: [{ model: Item, as: "item" }],
    });

    if (!rental) {
      throw new Error("Rental not found");
    }

    if (rental.ownerId !== userId) {
      throw new Error("Only the item owner can report damage");
    }

    if (!isActive(rental)) {
      throw new Error("Can only assess damage for active rentals");
    }

    // Validate required fields
    if (!description || description.trim().length === 0) {
      throw new Error("Damage description is required");
    }

    if (canBeFixed && (!repairCost || repairCost <= 0)) {
      throw new Error("Repair cost is required when item can be fixed");
    }

    if (needsReplacement && (!replacementCost || replacementCost <= 0)) {
      throw new Error(
        "Replacement cost is required when item needs replacement"
      );
    }

    // Calculate damage fees
    let damageFees = 0;
    let feeCalculation = {};

    if (needsReplacement) {
      // Full replacement cost
      damageFees = parseFloat(replacementCost);
      feeCalculation = {
        type: "replacement",
        amount: damageFees,
        originalCost: replacementCost,
        depreciation: 0,
      };
    } else if (canBeFixed && repairCost > 0) {
      // Repair cost
      damageFees = parseFloat(repairCost);
      feeCalculation = {
        type: "repair",
        amount: damageFees,
        repairCost: repairCost,
      };
    }

    // Process late return if applicable
    let lateFees = 0;
    let lateCalculation = null;

    if (actualReturnDateTime) {
      const lateReturn = await LateReturnService.processLateReturn(
        rentalId,
        actualReturnDateTime,
        `Item returned damaged: ${description}`
      );
      lateFees = lateReturn.lateCalculation.lateFee;
      lateCalculation = lateReturn.lateCalculation;
    }

    // Create damage assessment record as metadata
    const damageAssessment = {
      description,
      canBeFixed,
      repairCost: canBeFixed ? parseFloat(repairCost) : null,
      needsReplacement,
      replacementCost: needsReplacement ? parseFloat(replacementCost) : null,
      proofOfOwnership: proofOfOwnership || [],
      imageFilenames,
      assessedAt: new Date(),
      assessedBy: userId,
      feeCalculation,
    };

    // Update rental
    const updates = {
      status: "damaged",
      damageFees: damageFees,
      damageAssessment: damageAssessment,
    };

    // Add late fees if applicable
    if (lateFees > 0) {
      updates.lateFees = lateFees;
      updates.actualReturnDateTime = new Date(actualReturnDateTime);
    }

    const updatedRental = await rental.update(updates);

    // Fetch owner and renter user data for email
    const owner = await User.findByPk(updatedRental.ownerId);
    const renter = await User.findByPk(updatedRental.renterId);

    // Send damage report to customer service for review
    await emailServices.customerService.sendDamageReportToCustomerService(
      updatedRental,
      owner,
      renter,
      damageAssessment,
      lateCalculation
    );

    return {
      rental: updatedRental,
      damageAssessment,
      lateCalculation,
      totalAdditionalFees: damageFees + lateFees,
    };
  }
}

module.exports = DamageAssessmentService;
