const { Message, ConditionCheck, Rental } = require("../models");
const { Op } = require("sequelize");

/**
 * Service for verifying ownership/access to S3 files
 * Used to authorize signed URL requests for private content
 */
class S3OwnershipService {
  /**
   * Image size variant suffixes
   */
  static SIZE_SUFFIXES = ["_th", "_md"];

  /**
   * Extract the base key from a variant key (strips _th or _md suffix)
   * @param {string} key - S3 key like "messages/uuid_th.jpg" or "messages/uuid.jpg"
   * @returns {string} - Base key like "messages/uuid.jpg"
   */
  static getBaseKey(key) {
    if (!key) return key;
    for (const suffix of this.SIZE_SUFFIXES) {
      // Match suffix before file extension (e.g., _th.jpg, _md.png)
      const regex = new RegExp(`${suffix}(\\.[^.]+)$`);
      if (regex.test(key)) {
        return key.replace(regex, "$1");
      }
    }
    return key;
  }

  /**
   * Extract file type from S3 key
   * @param {string} key - S3 key like "messages/uuid.jpg"
   * @returns {string|null} - File type or null if unknown
   */
  static getFileTypeFromKey(key) {
    if (!key) return null;
    const folder = key.split("/")[0];
    const folderMap = {
      profiles: "profile",
      items: "item",
      messages: "message",
      forum: "forum",
      "condition-checks": "condition-check",
    };
    return folderMap[folder] || null;
  }

  /**
   * Verify if a user can access a file
   * @param {string} key - S3 key
   * @param {string} userId - User ID making the request
   * @returns {Promise<{authorized: boolean, reason?: string}>}
   */
  static async canAccessFile(key, userId) {
    const fileType = this.getFileTypeFromKey(key);

    switch (fileType) {
      case "profile":
      case "item":
      case "forum":
        // Public folders - anyone can access
        return { authorized: true };
      case "message":
        return this.verifyMessageAccess(key, userId);
      case "condition-check":
        return this.verifyConditionCheckAccess(key, userId);
      default:
        return { authorized: false, reason: "Unknown file type" };
    }
  }

  /**
   * Verify message image access - user must be sender OR receiver
   * @param {string} key - S3 key (may be variant like uuid_th.jpg)
   * @param {string} userId - User ID making the request
   * @returns {Promise<{authorized: boolean, reason?: string}>}
   */
  static async verifyMessageAccess(key, userId) {
    // Use base key for lookup (DB stores original key, not variants)
    const baseKey = this.getBaseKey(key);
    const message = await Message.findOne({
      where: {
        imageFilename: baseKey,
        [Op.or]: [{ senderId: userId }, { receiverId: userId }],
      },
    });
    return {
      authorized: !!message,
      reason: message ? null : "Not a participant in this message",
    };
  }

  /**
   * Verify condition check image access - user must be rental owner OR renter
   * @param {string} key - S3 key (may be variant like uuid_th.jpg)
   * @param {string} userId - User ID making the request
   * @returns {Promise<{authorized: boolean, reason?: string}>}
   */
  static async verifyConditionCheckAccess(key, userId) {
    // Use base key for lookup (DB stores original key, not variants)
    const baseKey = this.getBaseKey(key);
    const check = await ConditionCheck.findOne({
      where: {
        imageFilenames: { [Op.contains]: [baseKey] },
      },
      include: [
        {
          model: Rental,
          as: "rental",
          where: {
            [Op.or]: [{ ownerId: userId }, { renterId: userId }],
          },
        },
      ],
    });
    return {
      authorized: !!check,
      reason: check ? null : "Not a participant in this rental",
    };
  }
}

module.exports = S3OwnershipService;
