import { useCallback } from 'react';
import { useMatrixClient } from './useMatrixClient';
import { createAccountDataListStore } from './createAccountDataListStore';

export type Bookmark = {
  roomId: string;
  eventId: string;
  savedAt: number;
  previewText: string;
  roomName: string;
  // Author display name, snapshotted at save time. Optional for backward
  // compatibility with bookmarks stored before attribution was added; the panel
  // re-resolves a live name when the room is joined and falls back to this
  // snapshot otherwise. (We deliberately don't store the sender MXID — it's never
  // read back and would only grow the 500-entry account-data blob.)
  senderName?: string;
};

const BOOKMARKS_KEY = 'io.lotus.bookmarks';
const MAX_BOOKMARKS = 500;

type BookmarksContent = {
  bookmarks: Bookmark[];
};

// Shared, concurrency-safe store. See createAccountDataListStore for why the
// snapshot + write queue must be module-scoped (writes are serialized to avoid
// lost updates, since setAccountData replaces the whole content with no merge).
const bookmarksStore = createAccountDataListStore<Bookmark[], BookmarksContent>({
  eventType: BOOKMARKS_KEY,
  read: (content) => content?.bookmarks ?? [],
  write: (bookmarks) => ({ bookmarks }),
});

export function useBookmarks(): {
  bookmarks: Bookmark[];
  addBookmark: (b: Bookmark) => Promise<void>;
  removeBookmark: (eventId: string) => Promise<void>;
  isBookmarked: (eventId: string) => boolean;
} {
  const mx = useMatrixClient();
  const bookmarks = bookmarksStore.useValue(mx);

  const addBookmark = useCallback(
    (b: Bookmark) =>
      bookmarksStore.enqueueWrite(mx, (current) => {
        // Avoid duplicates
        const filtered = current.filter((bk) => bk.eventId !== b.eventId);
        let next = [b, ...filtered];
        if (next.length > MAX_BOOKMARKS) {
          next = next.slice(0, MAX_BOOKMARKS);
        }
        return next;
      }),
    [mx],
  );

  const removeBookmark = useCallback(
    (eventId: string) =>
      bookmarksStore.enqueueWrite(mx, (current) => current.filter((bk) => bk.eventId !== eventId)),
    [mx],
  );

  const isBookmarked = useCallback(
    (eventId: string) => bookmarks.some((bk) => bk.eventId === eventId),
    [bookmarks],
  );

  return { bookmarks, addBookmark, removeBookmark, isBookmarked };
}
