const { ConditionCheck, Rental, User } = require("../models");
const { Op } = require("sequelize");
const { isActive } = require("../utils/rentalStatus");

class ConditionCheckService {
  /**
   * Validate if a condition check can be submitted
   * @param {string} rentalId - Rental ID
   * @param {string} checkType - Type of check (pre_rental_owner, rental_start_renter, etc.)
   * @param {string} userId - User attempting to submit
   * @returns {Object} - { canSubmit, reason, timeWindow }
   */
  static async validateConditionCheck(rentalId, checkType, userId) {
    const rental = await Rental.findByPk(rentalId);

    if (!rental) {
      return { canSubmit: false, reason: "Rental not found" };
    }

    // Check user permissions
    const isOwner = rental.ownerId === userId;
    const isRenter = rental.renterId === userId;

    if (checkType.includes("owner") && !isOwner) {
      return {
        canSubmit: false,
        reason: "Only the item owner can submit owner condition checks",
      };
    }

    if (checkType.includes("renter") && !isRenter) {
      return {
        canSubmit: false,
        reason: "Only the renter can submit renter condition checks",
      };
    }

    // Check if already submitted
    const existingCheck = await ConditionCheck.findOne({
      where: { rentalId, checkType },
    });

    if (existingCheck) {
      return {
        canSubmit: false,
        reason: "Condition check already submitted for this type",
      };
    }

    // Check time windows (24 hour windows)
    const now = new Date();
    const startDate = new Date(rental.startDateTime);
    const endDate = new Date(rental.endDateTime);
    const twentyFourHours = 24 * 60 * 60 * 1000;

    let timeWindow = {};
    let canSubmit = false;

    switch (checkType) {
      case "pre_rental_owner":
        // 24 hours before rental starts
        timeWindow.start = new Date(startDate.getTime() - twentyFourHours);
        timeWindow.end = startDate;
        canSubmit = now >= timeWindow.start && now <= timeWindow.end;
        break;

      case "rental_start_renter":
        // 24 hours after rental starts
        timeWindow.start = startDate;
        timeWindow.end = new Date(startDate.getTime() + twentyFourHours);
        canSubmit =
          now >= timeWindow.start &&
          now <= timeWindow.end &&
          isActive(rental);
        break;

      case "rental_end_renter":
        // 24 hours before rental ends
        timeWindow.start = new Date(endDate.getTime() - twentyFourHours);
        timeWindow.end = endDate;
        canSubmit =
          now >= timeWindow.start &&
          now <= timeWindow.end &&
          isActive(rental);
        break;

      case "post_rental_owner":
        // Can be submitted anytime (integrated into return flow)
        timeWindow.start = endDate;
        timeWindow.end = null; // No time limit
        canSubmit = true; // Always allowed when owner marks return
        break;

      default:
        return { canSubmit: false, reason: "Invalid check type" };
    }

    if (!canSubmit) {
      const isBeforeWindow = now < timeWindow.start;
      const isAfterWindow = now > timeWindow.end;

      let reason = "Outside of allowed time window";
      if (isBeforeWindow) {
        reason = `Too early. Check can be submitted starting ${timeWindow.start.toLocaleString()}`;
      } else if (isAfterWindow) {
        reason = `Pre-Rental Condition can only be submitted before start of rental period`;
      }

      return { canSubmit: false, reason, timeWindow };
    }

    return { canSubmit: true, timeWindow };
  }

  /**
   * Submit a condition check with photos
   * @param {string} rentalId - Rental ID
   * @param {string} checkType - Type of check
   * @param {string} userId - User submitting the check
   * @param {Array} imageFilenames - Array of image filenames
   * @param {string} notes - Optional notes
   * @returns {Object} - Created condition check
   */
  static async submitConditionCheck(
    rentalId,
    checkType,
    userId,
    imageFilenames = [],
    notes = null
  ) {
    // Validate the check
    const validation = await this.validateConditionCheck(
      rentalId,
      checkType,
      userId
    );

    if (!validation.canSubmit) {
      throw new Error(validation.reason);
    }

    // Validate photos (basic validation)
    if (imageFilenames.length > 20) {
      throw new Error("Maximum 20 photos allowed per condition check");
    }

    const conditionCheck = await ConditionCheck.create({
      rentalId,
      checkType,
      submittedBy: userId,
      imageFilenames,
      notes,
    });

    return conditionCheck;
  }

  /**
   * Get all condition checks for multiple rentals (batch)
   * @param {Array<string>} rentalIds - Array of Rental IDs
   * @returns {Array} - Array of condition checks with user info
   */
  static async getConditionChecksForRentals(rentalIds) {
    if (!rentalIds || rentalIds.length === 0) {
      return [];
    }

    const checks = await ConditionCheck.findAll({
      where: {
        rentalId: {
          [Op.in]: rentalIds,
        },
      },
      include: [
        {
          model: User,
          as: "submittedByUser",
          attributes: ["id", "firstName", "lastName"],
        },
      ],
      order: [["submittedAt", "ASC"]],
    });

    return checks;
  }

  /**
   * Get available condition checks for a user
   * @param {string} userId - User ID
   * @param {Array<string>} rentalIds - Array of rental IDs to check
   * @returns {Array} - Array of available condition checks
   */
  static async getAvailableChecks(userId, rentalIds) {
    if (!rentalIds || rentalIds.length === 0) {
      return [];
    }

    const now = new Date();
    const twentyFourHours = 24 * 60 * 60 * 1000;

    // Find specified rentals where user is owner or renter
    const rentals = await Rental.findAll({
      where: {
        id: { [Op.in]: rentalIds },
        [Op.or]: [{ ownerId: userId }, { renterId: userId }],
        status: {
          [Op.in]: ["confirmed", "active", "completed"],
        },
      },
    });

    const availableChecks = [];

    for (const rental of rentals) {
      const isOwner = rental.ownerId === userId;
      const isRenter = rental.renterId === userId;
      const startDate = new Date(rental.startDateTime);
      const endDate = new Date(rental.endDateTime);

      // Check each type of condition check
      const checkTypes = [];

      if (isOwner) {
        // Only include pre_rental_owner; post_rental is now part of return flow
        checkTypes.push("pre_rental_owner");
      }
      if (isRenter) {
        checkTypes.push("rental_start_renter", "rental_end_renter");
      }

      for (const checkType of checkTypes) {
        // Check if already submitted
        const existing = await ConditionCheck.findOne({
          where: { rentalId: rental.id, checkType },
        });

        if (!existing) {
          const validation = await this.validateConditionCheck(
            rental.id,
            checkType,
            userId
          );

          if (validation.canSubmit) {
            availableChecks.push({
              rentalId: rental.id,
              checkType,
              rental: {
                id: rental.id,
                itemId: rental.itemId,
                startDateTime: rental.startDateTime,
                endDateTime: rental.endDateTime,
              },
              timeWindow: validation.timeWindow,
            });
          }
        }
      }
    }

    return availableChecks;
  }
}

module.exports = ConditionCheckService;
