import { MetaService } from "./meta.service";
const flagCache = {};
const CACHE_TTL = 5 * 60 * 1e3;
class UserFlagsService {
  /**
   * Get user flags from metadata
   */
  static async getUserFlags(userId) {
    try {
      const cached = flagCache[userId];
      if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
        return cached.flags;
      }
      const flagsMetadata = await MetaService.getEntityMetas("user", userId, userId, false);
      const accessMeta = flagsMetadata["access"];
      const flags = (accessMeta == null ? void 0 : accessMeta.flags) || [];
      const validFlags = this.validateFlags(flags);
      flagCache[userId] = {
        flags: validFlags,
        timestamp: Date.now()
      };
      return validFlags;
    } catch (error) {
      console.error("Error retrieving user flags:", error);
      return [];
    }
  }
  /**
   * Set user flags in metadata
   */
  static async setUserFlags(userId, flags) {
    try {
      const validFlags = this.validateFlags(flags);
      const existingAccessMeta = await MetaService.getSpecificEntityMetas("user", userId, ["access"], userId);
      const currentAccess = existingAccessMeta["access"] || {};
      const updatedAccess = {
        ...currentAccess,
        flags: validFlags
      };
      await MetaService.setEntityMeta("user", userId, "access", updatedAccess, userId);
      flagCache[userId] = {
        flags: validFlags,
        timestamp: Date.now()
      };
    } catch (error) {
      console.error("Error setting user flags:", error);
      throw new Error("Failed to set user flags");
    }
  }
  /**
   * Add a flag to user
   */
  static async addUserFlag(userId, flag) {
    const currentFlags = await this.getUserFlags(userId);
    if (!currentFlags.includes(flag)) {
      await this.setUserFlags(userId, [...currentFlags, flag]);
    }
  }
  /**
   * Remove a flag from user
   */
  static async removeUserFlag(userId, flag) {
    const currentFlags = await this.getUserFlags(userId);
    const updatedFlags = currentFlags.filter((f) => f !== flag);
    await this.setUserFlags(userId, updatedFlags);
  }
  /**
   * Check if user has a specific flag
   */
  static async hasFlag(userId, flag) {
    const flags = await this.getUserFlags(userId);
    return flags.includes(flag);
  }
  /**
   * Check if user has any of the specified flags
   */
  static async hasAnyFlag(userId, flags) {
    const userFlags = await this.getUserFlags(userId);
    return flags.some((flag) => userFlags.includes(flag));
  }
  /**
   * Check if user has all of the specified flags
   */
  static async hasAllFlags(userId, flags) {
    const userFlags = await this.getUserFlags(userId);
    return flags.every((flag) => userFlags.includes(flag));
  }
  /**
   * Validate flags array
   */
  static validateFlags(flags) {
    const validFlagValues = [
      "beta_tester",
      "early_adopter",
      "limited_access",
      "vip",
      "restricted",
      "experimental"
    ];
    return flags.filter((flag) => typeof flag === "string").filter((flag) => validFlagValues.includes(flag)).filter((flag, index, array) => array.indexOf(flag) === index);
  }
  /**
   * Clear cache for a user (useful when flags are updated externally)
   */
  static clearUserCache(userId) {
    delete flagCache[userId];
  }
  /**
   * Clear all cache (useful for testing)
   */
  static clearAllCache() {
    Object.keys(flagCache).forEach((userId) => {
      delete flagCache[userId];
    });
  }
  /**
   * Get bulk user flags for multiple users (optimized for performance)
   */
  static async getBulkUserFlags(userIds) {
    const result = {};
    const uncachedUsers = [];
    for (const userId of userIds) {
      const cached = flagCache[userId];
      if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
        result[userId] = cached.flags;
      } else {
        uncachedUsers.push(userId);
      }
    }
    if (uncachedUsers.length > 0) {
      try {
        const bulkMetadata = await MetaService.getBulkSpecificEntityMetas(
          "user",
          uncachedUsers,
          ["access"],
          uncachedUsers[0]
          // Use first user as requester (all users should have access to their own data)
        );
        for (const userId of uncachedUsers) {
          const userMetadata = bulkMetadata[userId] || {};
          const accessMeta = userMetadata["access"];
          const flags = this.validateFlags((accessMeta == null ? void 0 : accessMeta.flags) || []);
          result[userId] = flags;
          flagCache[userId] = {
            flags,
            timestamp: Date.now()
          };
        }
      } catch (error) {
        console.error("Error in bulk user flags retrieval:", error);
        uncachedUsers.forEach((userId) => {
          result[userId] = [];
        });
      }
    }
    return result;
  }
}
const getUserFlags = UserFlagsService.getUserFlags.bind(UserFlagsService);
const setUserFlags = UserFlagsService.setUserFlags.bind(UserFlagsService);
const addUserFlag = UserFlagsService.addUserFlag.bind(UserFlagsService);
const removeUserFlag = UserFlagsService.removeUserFlag.bind(UserFlagsService);
const hasFlag = UserFlagsService.hasFlag.bind(UserFlagsService);
const hasAnyFlag = UserFlagsService.hasAnyFlag.bind(UserFlagsService);
const hasAllFlags = UserFlagsService.hasAllFlags.bind(UserFlagsService);
const getBulkUserFlags = UserFlagsService.getBulkUserFlags.bind(UserFlagsService);
export {
  UserFlagsService,
  addUserFlag,
  getBulkUserFlags,
  getUserFlags,
  hasAllFlags,
  hasAnyFlag,
  hasFlag,
  removeUserFlag,
  setUserFlags
};
