const { getRedisClient } = require("./client") const USER_KEY_PREFIX = "data:users:" const USER_SAVED_SET_PREFIX = "data:users:saved:" const USER_UNSAVED_SET_PREFIX = "data:users:unsaved:" const DEFAULT_USER_TTL_SECONDS = 60 * 60 function createRedisClient() { return getRedisClient() } function normalizeUserId(userId) { const id = Number(userId) return Number.isInteger(id) && id > 0 ? id : null } async function ensureUserCache(userId, { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) { const id = normalizeUserId(userId) if (!id) return false const redis = createRedisClient() const key = `${USER_KEY_PREFIX}${id}` try { const exists = await redis.exists(key) if (!exists) { await redis.call( "JSON.SET", key, "$", JSON.stringify({ id, savedDeals: [] }) ) } if (ttlSeconds) { await redis.expire(key, Number(ttlSeconds)) } return true } finally {} } async function getUserSavedIdsFromRedis(userId) { const id = normalizeUserId(userId) if (!id) return [] const redis = createRedisClient() const key = `${USER_KEY_PREFIX}${id}` const setKey = `${USER_SAVED_SET_PREFIX}${id}` const unsavedKey = `${USER_UNSAVED_SET_PREFIX}${id}` try { const [raw, setIds, unsavedIds] = await Promise.all([ redis.call("JSON.GET", key, "$.savedDeals"), redis.smembers(setKey), redis.smembers(unsavedKey), ]) const fromJson = raw ? JSON.parse(raw) : [] const arr = Array.isArray(fromJson) ? (Array.isArray(fromJson[0]) ? fromJson[0] : fromJson) : [] const jsonIds = arr .map((v) => Number(v)) .filter((v) => Number.isInteger(v) && v > 0) const setList = (Array.isArray(setIds) ? setIds : []) .map((v) => Number(v)) .filter((v) => Number.isInteger(v) && v > 0) const unsavedList = (Array.isArray(unsavedIds) ? unsavedIds : []) .map((v) => Number(v)) .filter((v) => Number.isInteger(v) && v > 0) return { jsonIds, savedSet: new Set(setList), unsavedSet: new Set(unsavedList), } } finally {} } async function setUserSavedDeals(userId, ids = [], { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) { const uid = normalizeUserId(userId) if (!uid) return false const redis = createRedisClient() const key = `${USER_KEY_PREFIX}${uid}` try { const list = Array.isArray(ids) ? ids : [] await redis.call("JSON.SET", key, "$.savedDeals", JSON.stringify(list)) if (ttlSeconds) { await redis.expire(key, Number(ttlSeconds)) } return true } finally {} } async function addUserSavedDeal(userId, dealId, { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) { const uid = normalizeUserId(userId) const did = normalizeUserId(dealId) if (!uid || !did) return false const redis = createRedisClient() const key = `${USER_KEY_PREFIX}${uid}` const setKey = `${USER_SAVED_SET_PREFIX}${uid}` const unsavedKey = `${USER_UNSAVED_SET_PREFIX}${uid}` try { await ensureUserCache(uid, { ttlSeconds }) const raw = await redis.call("JSON.GET", key, "$.savedDeals") let list = [] if (raw) { const parsed = JSON.parse(raw) const arr = Array.isArray(parsed) ? parsed[0] : [] list = Array.isArray(arr) ? arr : [] } const exists = Array.isArray(list) ? list.some((v) => Number(v) === did) : false if (!exists) { list = [did, ...list] await redis.call("JSON.SET", key, "$.savedDeals", JSON.stringify(list)) } await redis.sadd(setKey, String(did)) await redis.srem(unsavedKey, String(did)) if (ttlSeconds) { await redis.expire(setKey, Number(ttlSeconds)) await redis.expire(unsavedKey, Number(ttlSeconds)) await redis.expire(key, Number(ttlSeconds)) } return true } finally {} } async function removeUserSavedDeal(userId, dealId, { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) { const uid = normalizeUserId(userId) const did = normalizeUserId(dealId) if (!uid || !did) return false const redis = createRedisClient() const key = `${USER_KEY_PREFIX}${uid}` const setKey = `${USER_SAVED_SET_PREFIX}${uid}` const unsavedKey = `${USER_UNSAVED_SET_PREFIX}${uid}` try { const raw = await redis.call("JSON.GET", key, "$.savedDeals") if (raw) { const parsed = JSON.parse(raw) const arr = Array.isArray(parsed) ? parsed[0] : [] const list = Array.isArray(arr) ? arr.filter((v) => Number(v) !== did) : [] await redis.call("JSON.SET", key, "$.savedDeals", JSON.stringify(list)) } await redis.srem(setKey, String(did)) await redis.sadd(unsavedKey, String(did)) if (ttlSeconds) { await redis.expire(setKey, Number(ttlSeconds)) await redis.expire(unsavedKey, Number(ttlSeconds)) await redis.expire(key, Number(ttlSeconds)) } return true } finally {} } module.exports = { ensureUserCache, getUserSavedIdsFromRedis, setUserSavedDeals, addUserSavedDeal, removeUserSavedDeal, }