const dealDB = require("../db/deal.db") const commentDB = require("../db/comment.db") const prisma = require("../db/client") function assertPositiveInt(v, name = "id") { const n = Number(v) if (!Number.isInteger(n) || n <= 0) throw new Error(`Geçersiz ${name}.`) return n } const DEFAULT_LIMIT = 20 const MAX_LIMIT = 50 const MAX_SKIP = 5000 function clampPagination({ page, limit }) { const rawPage = Number(page) const rawLimit = Number(limit) const normalizedPage = Number.isFinite(rawPage) ? Math.max(1, Math.floor(rawPage)) : 1 let normalizedLimit = Number.isFinite(rawLimit) ? Math.max(1, Math.floor(rawLimit)) : DEFAULT_LIMIT normalizedLimit = Math.min(MAX_LIMIT, normalizedLimit) const skip = (normalizedPage - 1) * normalizedLimit if (skip > MAX_SKIP) throw new Error("PAGE_TOO_DEEP") return { page: normalizedPage, limit: normalizedLimit, skip } } function parseParentId(value) { if (value === undefined) return null if (value === null) return null if (value === "" || value === "null") return null const pid = Number(value) if (!Number.isInteger(pid) || pid <= 0) throw new Error("Geçersiz 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 getCommentsByDealId(dealId, { parentId, page, limit, sort, viewer } = {}) { const id = Number(dealId) const deal = await dealDB.findDeal({ id }) if (!deal) throw new Error("Deal bulunamadı.") const include = { user: { select: { id: true, username: true, avatarUrl: true } }, _count: { select: { replies: true } }, } const pagination = clampPagination({ page, limit }) const parsedParentId = parseParentId(parentId) const sortMode = normalizeSort(sort) const orderBy = sortMode === "TOP" ? [{ likeCount: "desc" }, { createdAt: "desc" }] : [{ createdAt: "desc" }] const where = { dealId: id, parentId: parsedParentId } const [results, total] = await Promise.all([ commentDB.findComments(where, { include, orderBy, skip: pagination.skip, take: pagination.limit, }), commentDB.countComments(where), ]) let likedIds = new Set() if (viewer?.userId && results.length > 0) { const commentLikeDb = require("../db/commentLike.db") const likes = await commentLikeDb.findLikesByUserAndCommentIds( viewer.userId, results.map((c) => c.id) ) likedIds = new Set(likes.map((l) => l.commentId)) } const enriched = results.map((comment) => ({ ...comment, myLike: likedIds.has(comment.id), })) return { page: pagination.page, total, totalPages: Math.ceil(total / pagination.limit), results: enriched, } } async function createComment({ dealId, userId, text, parentId = null }) { if (!text || typeof text !== "string" || !text.trim()) { throw new Error("Yorum boş olamaz.") } const trimmed = text.trim() const include = { user: { select: { id: true, username: true, avatarUrl: true } } } return prisma.$transaction(async (tx) => { const deal = await dealDB.findDeal({ id: dealId }, { select: { id: true, status: true } }, tx) if (!deal) throw new Error("Deal bulunamadı.") if (deal.status !== "ACTIVE" && deal.status !== "EXPIRED") { throw new Error("Bu deal için yorum açılamaz.") } // ✅ Reply ise parent doğrula let parent = null if (parentId != null) { const pid = Number(parentId) if (!Number.isFinite(pid) || pid <= 0) throw new Error("Geçersiz parentId.") parent = await commentDB.findComment({ id: pid }, { select: { id: true, dealId: true } }, tx) if (!parent) throw new Error("Yanıtlanan yorum bulunamadı.") if (parent.dealId !== dealId) throw new Error("Yanıtlanan yorum bu deal'a ait değil.") } const comment = await commentDB.createComment( { text: trimmed, userId, dealId, parentId: parent ? parent.id : null, }, { include }, tx ) await dealDB.updateDeal( { id: dealId }, { commentCount: { increment: 1 } }, {}, tx ) return comment }) } async function deleteComment(commentId, userId) { const comment = await commentDB.findComment( { id: commentId }, { select: { userId: true, dealId: true, deletedAt: true } } ) if (!comment || comment.deletedAt) throw new Error("Yorum bulunamadı.") if (comment.userId !== userId) throw new Error("Bu yorumu silme yetkin yok.") await prisma.$transaction(async (tx) => { const result = await commentDB.softDeleteComment({ id: commentId, deletedAt: null }, tx) if (result.count > 0) { await dealDB.updateDeal( { id: comment.dealId }, { commentCount: { decrement: 1 } }, {}, tx ) } }) return { message: "Yorum silindi." } } async function commentChange(length,dealId){ } module.exports = { getCommentsByDealId, createComment, deleteComment, }