import { prisma } from '../../config/database';

const BLOCKED_USER_SELECT = {
  id: true,
  email: true,
  name: true,
} as const;

export const blockService = {
  /** Block a user. Auto-unfriends + removes from close friends. */
  async blockUser(userId: string, blockedUserId: string) {
    if (userId === blockedUserId) {
      throw Object.assign(new Error('Cannot block yourself'), { statusCode: 400 });
    }

    // Check target exists
    const target = await prisma.user.findUnique({ where: { id: blockedUserId }, select: { id: true } });
    if (!target) {
      throw Object.assign(new Error('User not found'), { statusCode: 404 });
    }

    // Check not already blocked
    const existing = await prisma.userBlock.findFirst({
      where: { userId, blockedUserId },
    });
    if (existing) {
      throw Object.assign(new Error('User already blocked'), { statusCode: 409 });
    }

    // Block + auto-unfriend + remove close friends in a transaction
    await prisma.$transaction([
      prisma.userBlock.create({ data: { userId, blockedUserId } }),
      // Remove any friendship between the two (either direction)
      prisma.friendship.deleteMany({
        where: {
          OR: [
            { userId, friendId: blockedUserId },
            { userId: blockedUserId, friendId: userId },
          ],
        },
      }),
      // Remove from close friends (either direction)
      prisma.closeFriend.deleteMany({
        where: {
          OR: [
            { userId, closeFriendId: blockedUserId },
            { userId: blockedUserId, closeFriendId: userId },
          ],
        },
      }),
    ]);

    return { success: true };
  },

  /** Unblock a user */
  async unblockUser(userId: string, blockedUserId: string) {
    const block = await prisma.userBlock.findFirst({
      where: { userId, blockedUserId },
    });

    if (!block) {
      throw Object.assign(new Error('User is not blocked'), { statusCode: 404 });
    }

    await prisma.userBlock.delete({ where: { id: block.id } });
    return { success: true };
  },

  /** List users blocked by this user */
  async listBlocked(userId: string) {
    const blocks = await prisma.userBlock.findMany({
      where: { userId },
      include: { blockedUser: { select: BLOCKED_USER_SELECT } },
      orderBy: { createdAt: 'desc' },
    });

    return blocks.map((b) => ({
      blockId: b.id,
      blockedAt: b.createdAt,
      user: b.blockedUser,
    }));
  },

  /** Check if either user has blocked the other */
  async isBlocked(userId: string, otherUserId: string): Promise<boolean> {
    const block = await prisma.userBlock.findFirst({
      where: {
        OR: [
          { userId, blockedUserId: otherUserId },
          { userId: otherUserId, blockedUserId: userId },
        ],
      },
    });
    return !!block;
  },
};
