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<string, string> = {};
  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<string, "like" | "dislike"> = {};
  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<string, SubEntry> = {};
  let userDomainVotes: Record<string, "yes" | "no"> = {};
  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,
  gameName?: string | null,
  i18nKey?: string | null,
) {
  const db = usePrisma();
  return db.communityPost.create({
    data: {
      userId,
      category,
      content,
      imageUrl: imageUrl || null,
      gameName: gameName ?? null,
      i18nKey: i18nKey ?? 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<string>();
  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 },
  });
}
