import { usePrisma } from "../utils/prisma"; // ─── Posts ──────────────────────────────────────────────────────────────────── export async function getPosts( category: string, page: number, limit: number, currentUserId: string | null, filterUserId?: string | null, ) { const db = usePrisma(); const offset = (page - 1) * limit; const where: any = { isModerated: false }; if (category !== "all") { if (category === "games") { where.category = { in: ["game_share", "challenge"] }; } else { where.category = category; } } if (filterUserId) { where.userId = filterUserId; } const posts = await db.communityPost.findMany({ where, orderBy: { createdAt: "desc" }, skip: offset, take: limit, include: { author: { select: { id: true, username: true, nickname: true, avatar: true, plan: true, }, }, repostOf: { include: { author: { select: { id: true, username: true, nickname: true, avatar: true, plan: true, }, }, }, }, }, }); // Batch: UserScore (tier) für alle Autoren laden const authorUserIds = [ ...new Set( posts .flatMap((p) => [p.userId, p.repostOf?.userId]) .filter((id): id is string => !!id), ), ]; let userScores: Record = {}; if (authorUserIds.length > 0) { const scores = await db.userScore.findMany({ where: { userId: { in: authorUserIds } }, select: { userId: true, tier: true }, }); for (const s of scores) userScores[s.userId] = s.tier; } // Eigene Likes laden wenn eingeloggt let userLikes: Record = {}; if (currentUserId && posts.length > 0) { const postIds = posts.map((p) => p.id); const likes = await db.postLike.findMany({ where: { userId: currentUserId, postId: { in: postIds } }, select: { postId: true, type: true }, }); for (const l of likes) { userLikes[l.postId] = l.type as "like" | "dislike"; } } // Challenge-Status für Challenge-Posts laden const challengeIds = posts .map((p) => (p as any).challengeId) .filter((id): id is string => !!id); let challengeStatuses: Record< string, { status: string; opponentId: string | null; opponentName: string | null; gameType: string | null; isLive: boolean; } > = {}; if (challengeIds.length > 0) { const challenges = await db.gameChallenge.findMany({ where: { id: { in: challengeIds } }, select: { id: true, status: true, opponentId: true, opponentName: true, gameType: true, isLive: true, }, }); for (const c of challenges) { challengeStatuses[c.id] = { status: c.status, opponentId: c.opponentId, opponentName: (c as any).opponentName ?? null, gameType: (c as any).gameType ?? null, isLive: (c as any).isLive ?? false, }; } } // Domain-Submission-Daten für domain_vote Posts laden const domainVotePostIds = posts .filter((p) => p.category === "domain_vote") .map((p) => p.id); type SubEntry = { id: string; domain: string; yesVotes: number; noVotes: number; status: string; reviewedAt: Date | null; }; let domainSubmissions: Record = {}; let userDomainVotes: Record = {}; let submissionVoters: Record< string, { yes: { id: string; nickname: string; avatar: string | null }[]; no: { id: string; nickname: string; avatar: string | null }[]; } > = {}; if (domainVotePostIds.length > 0) { const subs = await db.domainSubmission.findMany({ where: { postId: { in: domainVotePostIds } }, select: { id: true, postId: true, domain: true, yesVotes: true, noVotes: true, status: true, reviewedAt: true, }, }); for (const s of subs) { if (s.postId) domainSubmissions[s.postId] = { id: s.id, domain: s.domain, yesVotes: s.yesVotes, noVotes: s.noVotes, status: s.status, reviewedAt: s.reviewedAt ?? null, }; } if (currentUserId && subs.length > 0) { const votes = await db.domainVote.findMany({ where: { userId: currentUserId, submissionId: { in: subs.map((s) => s.id) }, }, select: { submissionId: true, vote: true }, }); const subIdToPostId = Object.fromEntries( Object.entries(domainSubmissions).map(([pid, s]) => [s.id, pid]), ); for (const v of votes) { const pid = subIdToPostId[v.submissionId]; if (pid) userDomainVotes[pid] = v.vote as "yes" | "no"; } } // Batch: DomainVote voters for domain submissions const submissionIds = Object.values(domainSubmissions) .map((s) => s.id) .filter(Boolean); if (submissionIds.length > 0) { const votes = await db.domainVote.findMany({ where: { submissionId: { in: submissionIds } }, select: { submissionId: true, vote: true, userId: true }, }); const voterIds = [...new Set(votes.map((v) => v.userId))]; let voterProfiles: Record< string, { nickname: string | null; avatar: string | null } > = {}; if (voterIds.length > 0) { const profiles = await db.profile.findMany({ where: { id: { in: voterIds } }, select: { id: true, nickname: true, avatar: true }, }); for (const p of profiles) voterProfiles[p.id] = { nickname: p.nickname, avatar: p.avatar }; } for (const v of votes) { if (!submissionVoters[v.submissionId]) submissionVoters[v.submissionId] = { yes: [], no: [] }; const profile = voterProfiles[v.userId]; const voter = { id: v.userId, nickname: profile?.nickname ?? "Nutzer", avatar: profile?.avatar ?? null, }; if (v.vote === "yes") submissionVoters[v.submissionId].yes.push(voter); else submissionVoters[v.submissionId].no.push(voter); } } } return { posts, userLikes, challengeStatuses, domainSubmissions, userDomainVotes, userScores, submissionVoters, }; } export async function getPostById(postId: string) { const db = usePrisma(); return db.communityPost.findUnique({ where: { id: postId }, include: { author: { select: { id: true, username: true, nickname: true, avatar: true, plan: true, }, }, }, }); } export async function createPost( userId: string, category: string, content: string, imageUrl?: string, ) { const db = usePrisma(); return db.communityPost.create({ data: { userId, category, content, imageUrl: imageUrl || null, isAnonymous: false, isModerated: false, }, include: { author: { select: { id: true, username: true, nickname: true, avatar: true, plan: true, }, }, }, }); } export async function deleteUserPosts(userId: string) { const db = usePrisma(); return db.communityPost.deleteMany({ where: { userId } }); } // ─── Likes ─────────────────────────────────────────────────────────────────── export async function getPostLike(userId: string, postId: string) { const db = usePrisma(); return db.postLike.findUnique({ where: { userId_postId: { userId, postId } }, select: { type: true }, }); } export async function setPostLike( userId: string, postId: string, type: "like" | "dislike", ) { const db = usePrisma(); return db.postLike.upsert({ where: { userId_postId: { userId, postId } }, create: { userId, postId, type }, update: { type }, }); } export async function deletePostLike(userId: string, postId: string) { const db = usePrisma(); return db.postLike.delete({ where: { userId_postId: { userId, postId } }, }); } export async function countPostLikes(postId: string) { const db = usePrisma(); const counts = await db.postLike.groupBy({ by: ["type"], where: { postId }, _count: { type: true }, }); const likes = counts.find((c) => c.type === "like")?._count.type ?? 0; const dislikes = counts.find((c) => c.type === "dislike")?._count.type ?? 0; return { likes, dislikes }; } export async function syncPostLikeCounts( postId: string, likes: number, dislikes: number, ) { const db = usePrisma(); return db.communityPost.update({ where: { id: postId }, data: { likesCount: likes, dislikesCount: dislikes }, }); } // ─── Comments (replies) ────────────────────────────────────────────────────── export async function getCommentsByPost( postId: string, currentUserId: string | null, ) { const db = usePrisma(); const comments = await db.communityReply.findMany({ where: { postId }, orderBy: { createdAt: "asc" }, take: 200, include: { author: { select: { id: true, username: true, nickname: true, avatar: true }, }, }, }); let userLikes = new Set(); if (currentUserId && comments.length > 0) { const commentIds = comments.map((c) => c.id); const likes = await db.commentLike.findMany({ where: { userId: currentUserId, commentId: { in: commentIds } }, select: { commentId: true }, }); for (const l of likes) { userLikes.add(l.commentId); } } return { comments, userLikes }; } export async function createComment( userId: string, postId: string, content: string, parentReplyId: string | null, ) { const db = usePrisma(); const [reply] = await Promise.all([ db.communityReply.create({ data: { userId, postId, content, parentReplyId, isAnonymous: false }, select: { id: true, content: true, createdAt: true, likesCount: true, parentReplyId: true, }, }), db.communityPost.update({ where: { id: postId }, data: { commentsCount: { increment: 1 } }, }), ]); return reply; } // ─── Comment Likes ──────────────────────────────────────────────────────────── export async function getCommentLike(userId: string, commentId: string) { const db = usePrisma(); return db.commentLike.findUnique({ where: { userId_commentId: { userId, commentId } }, }); } export async function createCommentLike(userId: string, commentId: string) { const db = usePrisma(); return db.commentLike.create({ data: { userId, commentId } }); } export async function deleteCommentLike(userId: string, commentId: string) { const db = usePrisma(); return db.commentLike.delete({ where: { userId_commentId: { userId, commentId } }, }); } export async function getCommentLikeCount(commentId: string) { const db = usePrisma(); return db.commentLike.count({ where: { commentId } }); } export async function syncCommentLikeCount(commentId: string, count: number) { const db = usePrisma(); return db.communityReply.update({ where: { id: commentId }, data: { likesCount: count }, }); }