import { isReviewApproved, Review } from "../../about/types/Types";

export type ReviewThread = {
  root: Review;
  replies: Review[];
};

export function getParentId(parent: Review["parent"]): string | null {
  if (!parent) return null;
  if (typeof parent === "string") return parent;
  if (typeof parent === "object" && "id" in parent) return parent.id;
  return null;
}

export function isPopulatedReview(value: Review["parent"]): value is Review {
  return Boolean(value && typeof value === "object" && "comment" in value);
}

export function getDisplayName(firstName?: string | null, lastName?: string | null, fallback = "کاربر"): string {
  return [firstName, lastName].filter(Boolean).join(" ") || fallback;
}

export function buildReviewThreads(reviews: Review[]): ReviewThread[] {
  const approved = reviews.filter(isReviewApproved);
  const topLevel = approved.filter((review) => !getParentId(review.parent));
  const topLevelById = new Map(topLevel.map((review) => [review.id, review]));

  const repliesByParentId = new Map<string, Review[]>();
  const orphanReplies: Review[] = [];

  for (const review of approved) {
    const parentId = getParentId(review.parent);
    if (!parentId) continue;

    if (topLevelById.has(parentId)) {
      const list = repliesByParentId.get(parentId) ?? [];
      list.push(review);
      repliesByParentId.set(parentId, list);
    } else {
      orphanReplies.push(review);
    }
  }

  const threads: ReviewThread[] = topLevel.map((root) => ({
    root,
    replies: (repliesByParentId.get(root.id) ?? []).sort(
      (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),
    ),
  }));

  for (const reply of orphanReplies) {
    if (isPopulatedReview(reply.parent)) {
      threads.push({
        root: reply.parent,
        replies: [reply],
      });
    }
  }

  return threads.sort((a, b) => new Date(b.root.createdAt).getTime() - new Date(a.root.createdAt).getTime());
}

export function resolveParentReview(reply: Review, threadRoot: Review): Review | null {
  if (isPopulatedReview(reply.parent)) {
    return reply.parent;
  }

  const parentId = getParentId(reply.parent);
  if (parentId && parentId === threadRoot.id) {
    return threadRoot;
  }

  return null;
}

export function reviewToUserMessage(review: Review): ChatMessage {
  return {
    id: review.id,
    type: "user",
    senderName: getDisplayName(review.user?.firstName, review.user?.lastName),
    content: review.comment || "نظری ثبت نشده است",
    createdAt: review.createdAt,
    rating: review.rating,
    positivePoints: review.positivePoints,
    negativePoints: review.negativePoints,
  };
}

export type ChatMessage = {
  id: string;
  type: "user" | "admin";
  senderName: string;
  content: string;
  createdAt?: string;
  rating?: number;
  positivePoints?: string[];
  negativePoints?: string[];
  parentMessage?: {
    senderName: string;
    content: string;
  };
};

export function buildThreadMessages(thread: ReviewThread): ChatMessage[] {
  const rootMessage = reviewToUserMessage(thread.root);
  const items: ChatMessage[] = [rootMessage];

  thread.replies.forEach((reply) => {
    const parentReview = resolveParentReview(reply, thread.root);
    const parentMessage = parentReview
      ? {
          senderName: getDisplayName(parentReview.user?.firstName, parentReview.user?.lastName),
          content: parentReview.comment || "-",
        }
      : undefined;

    items.push({
      id: reply.id,
      type: "admin",
      senderName: getDisplayName(reply.admin?.firstName, reply.admin?.lastName, "رستوران"),
      content: reply.comment || "-",
      createdAt: reply.createdAt,
      parentMessage,
    });
  });

  return items;
}

export function formatReviewMessageTime(date?: string) {
  if (!date) return "";

  return new Date(date).toLocaleString("fa-IR", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
  });
}
