export type ForkGroupingItem = {
  kind: "chat" | "search";
  id: string;
  parentChatId: string | null;
};

type ChatTitleState = {
  title: string | null;
  titleGenerationPending: boolean;
};

type ForkPresentationItem = ForkGroupingItem & {
  updatedAt: string;
  starred: boolean;
  starredAt: string | null;
};

export function groupForkedChatItems<T extends ForkGroupingItem>(items: T[]): T[][] {
  const groups = new Map<string, { firstIndex: number; items: Array<{ item: T; index: number }> }>();

  items.forEach((item, index) => {
    const groupKey = item.kind === "chat" ? `chat:${item.parentChatId ?? item.id}` : `search:${item.id}`;
    const group = groups.get(groupKey);
    if (group) {
      group.items.push({ item, index });
      return;
    }
    groups.set(groupKey, { firstIndex: index, items: [{ item, index }] });
  });

  return [...groups.values()]
    .sort((a, b) => a.firstIndex - b.firstIndex)
    .map((group) =>
      group.items
        .sort((a, b) => {
          const aIsRoot = a.item.kind === "chat" && a.item.parentChatId === null;
          const bIsRoot = b.item.kind === "chat" && b.item.parentChatId === null;
          if (aIsRoot !== bIsRoot) return aIsRoot ? -1 : 1;
          return a.index - b.index;
        })
        .map(({ item }) => item)
    );
}

export function filterSidebarItemsWithForkGroups<T extends ForkGroupingItem>(items: T[], matches: (item: T) => boolean): T[] {
  return groupForkedChatItems(items)
    .flatMap((group) => {
      const matchingItems = group.filter(matches);
      if (!matchingItems.length) return [];
      const root = group.find((item) => item.kind === "chat" && item.parentChatId === null);
      if (!root || matchingItems.includes(root)) return group;
      return group.filter((item) => item === root || matchingItems.includes(item));
    });
}

export function getForkGroupPresentation<T extends ForkPresentationItem>(groupItems: T[], allItems: T[]) {
  const firstItem = groupItems[0];
  if (!firstItem) return null;

  const rootId = firstItem.kind === "chat" ? firstItem.parentChatId ?? firstItem.id : null;
  const familyItems = rootId
    ? allItems.filter((item) => item.kind === "chat" && (item.id === rootId || item.parentChatId === rootId))
    : groupItems;
  const updatedAt = familyItems.reduce(
    (newest, item) => (new Date(item.updatedAt).getTime() > new Date(newest).getTime() ? item.updatedAt : newest),
    firstItem.updatedAt
  );
  const starOwner = rootId
    ? familyItems.find((item) => item.kind === "chat" && item.parentChatId === null)
    : firstItem;

  return {
    updatedAt,
    starred: starOwner?.starred ?? false,
    starredAt: starOwner?.starredAt ?? null,
  };
}

export function shouldRequestChatTitle(chat: ChatTitleState | null | undefined, isRequestInFlight: boolean) {
  if (!chat || isRequestInFlight) return false;
  return chat.titleGenerationPending || !chat.title?.trim();
}
