import { TRPCError } from "@trpc/server";

export const commentAuthorSelect = {
  id: true,
  name: true,
  email: true,
  image: true,
} as const;

export const commentWithAuthorInclude = {
  author: { select: commentAuthorSelect },
} as const;

export const commentThreadInclude = {
  author: { select: commentAuthorSelect },
  replies: {
    include: {
      author: { select: commentAuthorSelect },
    },
    orderBy: { createdAt: "asc" as const },
  },
} as const;

export function parseCommentMentions(body: string): string[] {
  const regex = /@\[([^\]]+)\]\(([^)]+)\)/g;
  const ids = new Set<string>();
  let match: RegExpExecArray | null;

  while ((match = regex.exec(body)) !== null) {
    ids.add(match[2]!);
  }

  return Array.from(ids);
}

export function buildCommentCreateData(input: {
  entityType: string;
  entityId: string;
  parentId?: string | undefined;
  authorId: string;
  body: string;
  mentions: string[];
}) {
  return {
    entityType: input.entityType,
    entityId: input.entityId,
    ...(input.parentId !== undefined ? { parentId: input.parentId } : {}),
    authorId: input.authorId,
    body: input.body,
    mentions: input.mentions,
  };
}

export function commentBelongsToEntity(input: {
  comment: {
    entityType: string;
    entityId: string;
  };
  entityType: string;
  entityId: string;
}): boolean {
  return (
    input.comment.entityType === input.entityType &&
    input.comment.entityId === input.entityId
  );
}

export function assertCommentManageableByActor(input: {
  authorId: string;
  actorUserId: string;
  isAdmin: boolean;
  action: "resolve" | "delete";
}) {
  if (input.authorId === input.actorUserId || input.isAdmin) {
    return;
  }

  throw new TRPCError({
    code: "FORBIDDEN",
    message: input.action === "resolve"
      ? "Only the comment author or an admin can resolve comments"
      : "Only the comment author or an admin can delete comments",
  });
}

function truncateCommentNotificationBody(body: string): string {
  return body.length > 120 ? `${body.slice(0, 120)}...` : body;
}

export function buildCommentMentionNotifications(input: {
  mentionedUserIds: string[];
  authorName: string;
  body: string;
  entityId: string;
  entityType: string;
  senderId: string;
  link: string;
}) {
  const truncatedBody = truncateCommentNotificationBody(input.body);

  return input.mentionedUserIds.map((userId) => ({
    userId,
    type: "COMMENT_MENTION" as const,
    title: `${input.authorName} mentioned you in a comment`,
    body: truncatedBody,
    entityId: input.entityId,
    entityType: input.entityType,
    senderId: input.senderId,
    link: input.link,
    channel: "in_app" as const,
  }));
}
