const userDB = require("../db/user.db") const commentDB = require("../db/comment.db") const { addCommentToRedis, removeCommentFromRedis, getCommentsForDeal, } = require("./redis/commentCache.service") const { getOrCacheDeal, getDealIdByCommentId } = require("./redis/dealCache.service") const { generateCommentId } = require("./redis/commentId.service") const { queueCommentCreate, queueCommentDelete } = require("./redis/dbSync.service") function parseParentId(value) { if (value === undefined || value === null || value === "" || value === "null") return null const pid = Number(value) if (!Number.isInteger(pid) || pid <= 0) throw new Error("Gecersiz parentId.") return pid } function normalizeSort(value) { const normalized = String(value || "new").trim().toLowerCase() if (["top", "best", "liked"].includes(normalized)) return "TOP" return "NEW" } async function ensureDealCached(dealId) { return getOrCacheDeal(dealId, { ttlSeconds: 15 * 60 }) } async function getCommentsByDealId(dealId, { parentId, page, limit, sort, viewer } = {}) { const id = Number(dealId) const deal = await ensureDealCached(id) if (!deal) throw new Error("Deal bulunamadi.") return getCommentsForDeal({ dealId: id, deal, parentId: parseParentId(parentId), page, limit, sort: normalizeSort(sort), viewerId: viewer?.userId ?? null, }) } async function createComment({ dealId, userId, text, parentId = null }) { if (!text || typeof text !== "string" || !text.trim()) { throw new Error("Yorum bos olamaz.") } const deal = await ensureDealCached(dealId) if (!deal) throw new Error("Deal bulunamadi.") if (deal.status !== "ACTIVE" && deal.status !== "EXPIRED") { throw new Error("Bu deal icin yorum acilamaz.") } let parent = null if (parentId != null) { const pid = parseParentId(parentId) const comments = Array.isArray(deal.comments) ? deal.comments : [] const cachedParent = comments.find((c) => Number(c.id) === Number(pid)) if (!cachedParent || cachedParent.deletedAt) throw new Error("Yanıtlanan yorum bulunamadi.") if (Number(cachedParent.dealId) !== Number(dealId)) { throw new Error("Yanıtlanan yorum bu deal'a ait degil.") } parent = { id: cachedParent.id, dealId: cachedParent.dealId } } const user = await userDB.findUser( { id: userId }, { select: { id: true, username: true, avatarUrl: true } } ) if (!user) throw new Error("Kullanici bulunamadi.") const createdAt = new Date() const commentId = await generateCommentId() const comment = { id: commentId, text: text.trim(), userId, dealId, parentId: parent ? parent.id : null, createdAt, likeCount: 0, repliesCount: 0, user, } await addCommentToRedis({ ...comment, repliesCount: 0, }) queueCommentCreate({ commentId, dealId, userId, text: text.trim(), parentId: parent ? parent.id : null, createdAt: createdAt.toISOString(), }).catch((err) => console.error("DB sync comment create failed:", err?.message || err)) return comment } async function deleteComment(commentId, userId) { const cid = Number(commentId) if (!Number.isInteger(cid) || cid <= 0) throw new Error("Gecersiz commentId.") let dealId = await getDealIdByCommentId(cid) let dbFallback = null if (!dealId) { dbFallback = await commentDB.findComment( { id: cid }, { select: { id: true, dealId: true, userId: true, parentId: true, deletedAt: true } } ) if (!dbFallback || dbFallback.deletedAt) throw new Error("Yorum bulunamadi.") dealId = dbFallback.dealId } const deal = await ensureDealCached(dealId) if (!deal) throw new Error("Yorum bulunamadi.") const comments = Array.isArray(deal.comments) ? deal.comments : [] const comment = comments.find((c) => Number(c.id) === cid) const effective = comment || dbFallback if (!effective || effective.deletedAt) throw new Error("Yorum bulunamadi.") if (Number(effective.userId) !== Number(userId)) throw new Error("Bu yorumu silme yetkin yok.") queueCommentDelete({ commentId: cid, dealId: effective.dealId, createdAt: new Date().toISOString(), }).catch((err) => console.error("DB sync comment delete failed:", err?.message || err)) await removeCommentFromRedis({ commentId: cid, dealId: effective.dealId, }) return { message: "Yorum silindi." } } async function deleteCommentAsMod(commentId) { const cid = Number(commentId) if (!Number.isInteger(cid) || cid <= 0) throw new Error("Gecersiz commentId.") let dealId = await getDealIdByCommentId(cid) let dbFallback = null if (!dealId) { dbFallback = await commentDB.findComment( { id: cid }, { select: { id: true, dealId: true, userId: true, parentId: true, deletedAt: true } } ) if (!dbFallback || dbFallback.deletedAt) throw new Error("Yorum bulunamadi.") dealId = dbFallback.dealId } const deal = await ensureDealCached(dealId) if (!deal) throw new Error("Yorum bulunamadi.") const comments = Array.isArray(deal.comments) ? deal.comments : [] const comment = comments.find((c) => Number(c.id) === cid) const effective = comment || dbFallback if (!effective || effective.deletedAt) throw new Error("Yorum bulunamadi.") queueCommentDelete({ commentId: cid, dealId: effective.dealId, createdAt: new Date().toISOString(), }).catch((err) => console.error("DB sync comment delete failed:", err?.message || err)) await removeCommentFromRedis({ commentId: cid, dealId: effective.dealId, }) return { message: "Yorum silindi." } } module.exports = { getCommentsByDealId, createComment, deleteComment, deleteCommentAsMod, }