import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
  sharing,
  type PendingSharesResponse,
  type SharedFolder,
  type SharedHeap,
} from '../services/api'
import { useAuth } from '../contexts/AuthContext'
import { formatApiError } from '../lib/apiError'
import { toast } from '../components/ToastContainer'

export const SHARED_HEAPS_KEY = ['sharing', 'heaps'] as const
export const SHARED_FOLDERS_KEY = ['sharing', 'folders'] as const
export const PENDING_SHARES_KEY = ['sharing', 'pending'] as const

export function useSharedHeapsQuery() {
  return useQuery<SharedHeap[]>({
    queryKey: SHARED_HEAPS_KEY,
    queryFn: sharing.sharedHeaps,
    staleTime: 30_000,
  })
}

export function useSharedFoldersQuery() {
  return useQuery<SharedFolder[]>({
    queryKey: SHARED_FOLDERS_KEY,
    queryFn: sharing.sharedFolders,
    staleTime: 30_000,
  })
}

/** Pending invites powering the notification bell in the sidebar.
 *  Polls at 60s — invites don't need real-time, and the user can also
 *  manually trigger the popover to force a refetch. Gated on the
 *  auth'd user so we don't hammer /sharing/pending from the login
 *  screen before any tokens are available. */
export function usePendingSharesQuery() {
  const { user } = useAuth()
  return useQuery<PendingSharesResponse>({
    queryKey: PENDING_SHARES_KEY,
    queryFn: sharing.pendingShares,
    enabled: !!user,
    staleTime: 30_000,
    refetchInterval: 60_000,
    // Keep the stale data visible while the refetch is in flight —
    // prevents the bell badge from flickering to 0 on every poll.
    placeholderData: (prev) => prev,
  })
}

interface ShareAction {
  kind: 'heap' | 'folder'
  targetId: string
}

/** Invalidate both the pending-list and the accepted-list keys after
 *  accept/decline/revoke-self so the bell count and the sidebar
 *  "Shared with me" section update together. */
function invalidateShareKeys(queryClient: ReturnType<typeof useQueryClient>) {
  queryClient.invalidateQueries({ queryKey: PENDING_SHARES_KEY })
  queryClient.invalidateQueries({ queryKey: SHARED_HEAPS_KEY })
  queryClient.invalidateQueries({ queryKey: SHARED_FOLDERS_KEY })
}

export function useAcceptShareMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: ({ kind, targetId }: ShareAction) =>
      kind === 'heap'
        ? sharing.acceptHeapShare(targetId)
        : sharing.acceptFolderShare(targetId),
    onSuccess: () => invalidateShareKeys(queryClient),
    onError: (err: any) => {
      // 404 = the owner revoked (or we raced a previous decline).
      // Surface a softer message and refresh the list instead of a
      // hard error toast.
      if (err?.response?.status === 404) {
        toast.info('Invite no longer available', 'The sender may have revoked it.')
        invalidateShareKeys(queryClient)
        return
      }
      toast.error('Could not accept', formatApiError(err))
    },
  })
}

export function useDeclineShareMutation() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: ({ kind, targetId }: ShareAction) =>
      kind === 'heap'
        ? sharing.declineHeapShare(targetId)
        : sharing.declineFolderShare(targetId),
    onSuccess: () => invalidateShareKeys(queryClient),
    onError: (err: any) => {
      if (err?.response?.status === 404) {
        invalidateShareKeys(queryClient)
        return
      }
      toast.error('Could not decline', formatApiError(err))
    },
  })
}
