import { infiniteQueryOptions, queryOptions } from '@tanstack/react-query'
import {
  getMastodonListAccounts,
  getMastodonLists,
  getMastodonListsForAccount,
} from 'src/lib/api'
import type { MastodonList } from 'src/lib/api/mastodon'
import type { Account } from 'src/lib/api-types'
import { buildMembershipMap, type MembershipMap } from 'src/lib/lists/membershipMap'
import type { LinkPaginatedResponse } from 'src/lib/pagination'
import { queryKeys } from './keys'

// Mastodon-only list catalogue — Phase B §3.3 of the Mastodon follow-up plan.
// `getMastodonLists` is `mastodonActiveContext()`-asserted, so consumers must
// gate on `user.type === 'mastodon'` before subscribing.
export const listsQueries = {
  lists: () =>
    queryOptions<MastodonList[]>({
      queryKey: queryKeys.lists.lists(),
      queryFn: getMastodonLists,
      staleTime: 5 * 60 * 1000,
      gcTime: 60 * 60 * 1000,
    }),

  // Members of one list — paginated via Link headers (same shape as
  // followers / following), so consumers wire it through useInfiniteQuery.
  accounts: (listId: string) =>
    infiniteQueryOptions({
      queryKey: queryKeys.lists.accounts(listId),
      queryFn: ({ pageParam }) =>
        getMastodonListAccounts({ listId, pageParam: pageParam as string | false }),
      initialPageParam: false as string | false,
      staleTime: 60 * 1000,
      gcTime: 30 * 60 * 1000,
      getNextPageParam: (lastPage: LinkPaginatedResponse<Account>) =>
        lastPage.nextPage ?? undefined,
      getPreviousPageParam: (lastPage: LinkPaginatedResponse<Account>) =>
        lastPage.prevPage ?? undefined,
    }),

  // Inverse lookup — the catalogue subset a single account belongs to.
  // Unpaginated array on the wire; small enough for a plain queryOptions.
  forAccount: (accountId: string) =>
    queryOptions<MastodonList[]>({
      queryKey: queryKeys.lists.forAccount(accountId),
      queryFn: () => getMastodonListsForAccount(accountId),
      staleTime: 60 * 1000,
      gcTime: 30 * 60 * 1000,
    }),

  // List Organizer's derived `accountId → listIds[]` map. The queryFn fans out
  // every list's members (`buildMembershipMap`) and returns one JSON-friendly
  // map, so it rides the default persister: the fan-out runs on the first cold
  // open, then repeat opens hydrate from disk instantly and refetch in the
  // background once stale. Keyed on the sorted list-id set so adding/removing a
  // list re-keys the slice. Mastodon-only — gate the consumer on
  // `user.type === 'mastodon'`.
  membershipMap: (listIds: string[]) => {
    const listKey = [...listIds].sort().join('|')
    return queryOptions<MembershipMap>({
      queryKey: queryKeys.lists.membershipMap(listKey),
      queryFn: () => buildMembershipMap(listIds),
      staleTime: 5 * 60 * 1000,
      gcTime: 24 * 60 * 60 * 1000,
    })
  },
}
