import { getMastodonListAccounts } from 'src/lib/api/mastodon'

// Membership map for the List Organizer (Surface E): the inverse of the
// catalogue — which lists each followed account belongs to. Built once by
// fanning out `/api/v1/lists/:id/accounts` across every list and powering the
// per-row colour dots + the "Listless" filter.
//
// Shape (accountId → listIds) is JSON-serialisable, so the derived map rides
// the default React Query persister for free (see `listsQueries.membershipMap`)
// — instant on repeat opens, background-refetched when stale. The fan-out loop
// used to live in `organize.tsx`'s `useListMemberships`; it moved here so the
// queryFn and the screen share one definition and it can be unit-tested.

export type MembershipMap = Record<string, string[]> // accountId → listIds

// Per-list ceiling — Listless degrades past this; mirrors the cap the organizer
// shipped with. A list with more than this many members stops contributing new
// dots, but the dots it does carry stay correct.
export const MEMBER_CAP = 500

// Pure, idempotent: returns `prev` unchanged when the account is already in the
// list (so a redundant drop never produces a duplicate dot or a new reference).
export function addMembershipLocal(
  prev: MembershipMap,
  accountId: string,
  listId: string
): MembershipMap {
  const cur = prev[accountId] ?? []
  if (cur.includes(listId)) return prev
  return { ...prev, [accountId]: [...cur, listId] }
}

// Fan out across every list's members and fold them into one map. Each list is
// paginated independently and capped at `cap`; a single list failing (rate
// limit, 500-cap) is swallowed so it never aborts the others.
export async function buildMembershipMap(
  listIds: string[],
  cap = MEMBER_CAP
): Promise<MembershipMap> {
  const map: MembershipMap = {}
  for (const listId of listIds) {
    let pageParam: string | false = false
    let count = 0
    try {
      do {
        const page = await getMastodonListAccounts({ listId, pageParam })
        for (const acc of page.data) {
          ;(map[acc.id] ??= []).push(listId)
        }
        count += page.data.length
        pageParam = page.nextPage ?? false
      } while (pageParam && count < cap)
    } catch {
      // One list failing must not abort the rest of the fan-out.
    }
  }
  return map
}
