'use client'

import type { DocumentProcessingTask } from '@dify/contracts/knowledge-fs/types.gen'
import type {
  ProcessingTaskEvent,
  ProcessingTaskProgressEvent,
} from './services/processing-task-events'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { toast } from '@langgenius/dify-ui/toast'
import { useInfiniteQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useAtomValue, useSetAtom } from 'jotai'
import { debounce, parseAsString, parseAsStringLiteral, useQueryState } from 'nuqs'
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import {
  datasetDefaultPermissionKeysAtom,
  refreshWorkspacePermissionKeysAfterMutationDenialAtom,
  retryWorkspacePermissionKeysAtom,
  workspacePermissionKeysErrorAtom,
  workspacePermissionKeysFetchingAtom,
  workspacePermissionKeysLoadingAtom,
} from '@/context/permission-state'
import { consoleClient, consoleQuery } from '@/service/client'
import { DatasetACLPermission, hasPermission } from '@/utils/permission'
import { useAuxiliaryTaskReadGuard } from './auxiliary-task-read-guard'
import { DocumentBulkActions, DocumentsEmpty, DocumentsList } from './document-list'
import {
  ACTIVE_TASK_STATES,
  documentDisplayStatus,
  newestTaskByDocument,
  sourceName,
  taskIsActive,
  taskNeedsAttention,
  taskVersionIsAfter,
} from './document-model'
import { DOCUMENT_UPLOAD_ACCEPT, documentUploadIssue } from './document-upload-policy'
import { ProcessingTasksDrawer } from './processing-tasks-drawer'
import { newKnowledgeDocumentDetailPath } from './routes'
import { TaskEventObserver } from './task-event-observer'
import { createTaskProgressStore } from './task-progress-store'
import { useQueryDataUpdateCount } from './use-query-data-update-count'

const DOCUMENT_PAGE_SIZE = 50
const TASK_PAGE_SIZE = 100
const MAX_TASK_EVENT_STREAMS = 6
const MAX_AUTO_CURSOR_PAGES = 20
const FAILED_TASK_POLL_REQUEST_TIMEOUT = 3000
const TERMINAL_RECONCILIATION_REQUEST_TIMEOUT = 3000
const BLOCKED_ACTIVE_TASK_REFRESH_INTERVAL = 5000
const MAX_BLOCKED_ACTIVE_TASK_REFRESH_INTERVAL = 30000
const documentFilterParser = parseAsStringLiteral([
  'all',
  'ready',
  'queued',
  'processing',
  'failed',
  'disabled',
] as const)
  .withDefault('all')
  .withOptions({ history: 'push' })
const documentSearchParser = parseAsString.withDefault('').withOptions({
  limitUrlUpdates: debounce(300),
})

const uploadExclusionReasonKey = {
  batch_byte_limit_exceeded: 'batchLimit',
  document_not_found: 'target',
  file_count_limit_exceeded: 'countLimit',
  file_too_large: 'fileSize',
  invalid_file: 'fileType',
  invalid_target: 'target',
  processing_failed: 'processing',
  quota_exceeded: 'quota',
  revision_conflict: 'target',
  unsupported_mime_type: 'fileType',
} as const

type UploadExclusionReasonKey =
  (typeof uploadExclusionReasonKey)[keyof typeof uploadExclusionReasonKey]

type TerminalTaskPin = {
  observedAt: string
  taskListGeneration: number
}

type TrustedActiveOverride = {
  taskListGeneration: number
  updatedAt: string
}

type AuxiliaryTaskReadDenial = {
  taskListGeneration: number
  taskVersion: string
}

const DOCUMENT_PERMISSION_DENIED = 1
const TASK_PERMISSION_DENIED = 2
const SOURCE_PERMISSION_DENIED = 4

function recoveryQueryMaskForPermissionDenials(permissionDenialMask: number) {
  let recoveryQueryMask = 0
  if (permissionDenialMask & DOCUMENT_PERMISSION_DENIED)
    recoveryQueryMask |= TASK_PERMISSION_DENIED | SOURCE_PERMISSION_DENIED
  if (permissionDenialMask & TASK_PERMISSION_DENIED) recoveryQueryMask |= SOURCE_PERMISSION_DENIED
  if (permissionDenialMask & SOURCE_PERMISSION_DENIED) recoveryQueryMask |= TASK_PERMISSION_DENIED
  return recoveryQueryMask & ~permissionDenialMask
}

function responseStatus(error: unknown): number | undefined {
  if (error instanceof Response) return error.status
  if (error && typeof error === 'object' && 'status' in error)
    return typeof error.status === 'number' ? error.status : undefined
  if (error && typeof error === 'object' && 'data' in error) {
    const data = error.data
    if (data && typeof data === 'object' && 'status' in data)
      return typeof data.status === 'number' ? data.status : undefined
  }
}

function taskSnapshotErrorIsTransient(error: unknown) {
  const status = responseStatus(error)
  return status === undefined || status === 408 || status === 429 || status >= 500
}

function queryKeyMatchesKnowledgeSpace(queryKey: readonly unknown[], knowledgeSpaceId: string) {
  const state = queryKey[1]
  if (!state || typeof state !== 'object' || !('input' in state)) return false
  const input = state.input
  if (!input || typeof input !== 'object' || !('params' in input)) return false
  const params = input.params
  return Boolean(
    params && typeof params === 'object' && 'id' in params && params.id === knowledgeSpaceId,
  )
}

function normalizedTaskSnapshot(task: DocumentProcessingTask): DocumentProcessingTask {
  return {
    ...task,
    errorCode: task.errorCode,
    errorMessage: task.errorMessage,
  }
}

export function DocumentsPage({ knowledgeSpaceId }: { knowledgeSpaceId: string }) {
  const { t } = useTranslation('dataset')
  const { t: tCommon } = useTranslation('common')
  const queryClient = useQueryClient()
  const datasetDefaultPermissionKeys = useAtomValue(datasetDefaultPermissionKeysAtom)
  const workspacePermissionKeysLoading = useAtomValue(workspacePermissionKeysLoadingAtom)
  const workspacePermissionKeysFetching = useAtomValue(workspacePermissionKeysFetchingAtom)
  const workspacePermissionKeysError = useAtomValue(workspacePermissionKeysErrorAtom)
  const retryWorkspacePermissionKeys = useSetAtom(retryWorkspacePermissionKeysAtom)
  const refreshWorkspacePermissionKeysAfterMutationDenial = useSetAtom(
    refreshWorkspacePermissionKeysAfterMutationDenialAtom,
  )
  const canEdit = hasPermission(datasetDefaultPermissionKeys, DatasetACLPermission.Edit)
  const permissionPending = workspacePermissionKeysLoading
  const permissionQueryError = Boolean(workspacePermissionKeysError)
  const hasWorkspaceWritePermission = canEdit && !permissionPending && !permissionQueryError
  const uploadInputRef = useRef<HTMLInputElement>(null)
  const documentPermissionAlertRef = useRef<HTMLDivElement>(null)
  const writePermissionFocusRecoveryRequestedRef = useRef(false)
  const writePermissionFocusOriginRef = useRef<HTMLElement | null>(null)
  const uploadPendingRef = useRef(false)
  const reindexPendingRef = useRef(false)
  const [filter, setFilter] = useQueryState('status', documentFilterParser)
  const [search, setSearch] = useQueryState('query', documentSearchParser)
  const [selectedDocumentIds, setSelectedDocumentIds] = useState<Set<string>>(() => new Set())
  const [tasksOpen, setTasksOpen] = useState(false)
  const [writePermissionRevoked, setWritePermissionRevoked] = useState(false)
  const [writePermissionRecoveryGeneration, setWritePermissionRecoveryGeneration] = useState<
    number | undefined
  >()
  const writePermissionDenialGenerationRef = useRef(0)
  const writePermissionRecoveryFetchSeenRef = useRef(false)
  const [blockingDependencyRetries, setBlockingDependencyRetries] = useState({
    sources: false,
    tasks: false,
  })
  const [taskStreamOffset, setTaskStreamOffset] = useState(0)
  const failedTaskPollOffsetRef = useRef(0)
  const [taskOverrides, setTaskOverrides] = useState<
    Record<string, Partial<DocumentProcessingTask>>
  >({})
  const [terminalTaskPins, setTerminalTaskPins] = useState<Record<string, TerminalTaskPin>>({})
  const [taskObserverGenerations, setTaskObserverGenerations] = useState<Record<string, number>>({})
  const terminalReconciliationGenerationsRef = useRef(new Map<string, number>())
  const failedTaskPollGenerationsRef = useRef(new Map<string, number>())
  const blockedFailedTaskPollVersionsRef = useRef(new Map<string, string>())
  const failedPollAuxiliaryDenialsRef = useRef(new Map<string, AuxiliaryTaskReadDenial>())
  const terminalConfirmableAuxiliaryDenialsRef = useRef(new Map<string, AuxiliaryTaskReadDenial>())
  const equalRetryListGenerationsRef = useRef(new Map<string, number>())
  const terminalReconciliationTimeoutsRef = useRef(new Map<string, number>())
  const terminalReconciliationControllersRef = useRef(new Map<string, AbortController>())
  const pendingTerminalProgressRef = useRef(new Map<string, ProcessingTaskProgressEvent>())
  const taskEventCursorsRef = useRef(new Map<string, string>())
  const streamActiveOverrideVersionsRef = useRef(new Map<string, string>())
  const trustedActiveOverrideVersionsRef = useRef(new Map<string, TrustedActiveOverride>())
  const trustedOverrideListGenerationsRef = useRef(new Map<string, number>())
  const taskProgressStoreRef = useRef<ReturnType<typeof createTaskProgressStore> | null>(null)
  if (!taskProgressStoreRef.current) taskProgressStoreRef.current = createTaskProgressStore()
  const taskProgressStore = taskProgressStoreRef.current
  const [uploading, setUploading] = useState(false)
  const [reindexing, setReindexing] = useState(false)
  const { mutateAsync: uploadDocument } = useMutation(
    consoleQuery.knowledgeFs.postKnowledgeSpacesByIdDocuments.mutationOptions(),
  )
  const { mutateAsync: bulkUploadDocuments } = useMutation(
    consoleQuery.knowledgeFs.postKnowledgeSpacesByIdDocumentsBulk.mutationOptions(),
  )
  const { mutateAsync: reindexDocuments } = useMutation(
    consoleQuery.knowledgeFs.postKnowledgeSpacesByIdDocumentsBulkReindex.mutationOptions(),
  )

  const documentsQuery = useInfiniteQuery(
    consoleQuery.knowledgeFs.getKnowledgeSpacesByIdLogicalDocuments.infiniteOptions({
      input: (pageParam) => ({
        params: { id: knowledgeSpaceId },
        query: {
          limit: DOCUMENT_PAGE_SIZE,
          ...(typeof pageParam === 'string' ? { cursor: pageParam } : {}),
        },
      }),
      getNextPageParam: (lastPage) => lastPage.nextCursor,
      initialPageParam: null as string | null,
    }),
  )
  const documentPermissionDenied = responseStatus(documentsQuery.error) === 403
  const refetchDocumentsQuery = documentsQuery.refetch
  const {
    deny: denyAuxiliaryTaskRead,
    guard: auxiliaryTaskReadGuard,
    permissionDenied: auxiliaryReadPermissionDenied,
    retry: retryAuxiliaryTaskRead,
  } = useAuxiliaryTaskReadGuard({
    documentPermissionDenied,
    refetchDocuments: refetchDocumentsQuery,
  })
  useEffect(() => {
    if (!documentPermissionDenied) return
    failedPollAuxiliaryDenialsRef.current.clear()
    terminalConfirmableAuxiliaryDenialsRef.current.clear()
  }, [documentPermissionDenied])
  const tasksQueryOptions = useMemo(
    () =>
      consoleQuery.knowledgeFs.getKnowledgeSpacesByIdProcessingTasks.infiniteOptions({
        enabled: !documentPermissionDenied,
        input: (pageParam) => ({
          params: { id: knowledgeSpaceId },
          query: {
            limit: TASK_PAGE_SIZE,
            ...(typeof pageParam === 'string' ? { cursor: pageParam } : {}),
          },
        }),
        getNextPageParam: (lastPage) => lastPage.nextCursor,
        initialPageParam: null as string | null,
      }),
    [documentPermissionDenied, knowledgeSpaceId],
  )
  const tasksQuery = useInfiniteQuery(tasksQueryOptions)
  const sourcesQuery = useInfiniteQuery(
    consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSources.infiniteOptions({
      enabled: !documentPermissionDenied,
      input: (pageParam) => ({
        params: { id: knowledgeSpaceId },
        query: {
          limit: TASK_PAGE_SIZE,
          ...(typeof pageParam === 'string' ? { cursor: pageParam } : {}),
        },
      }),
      getNextPageParam: (lastPage) => lastPage.nextCursor,
      initialPageParam: null as string | null,
    }),
  )
  const permissionDenialMask =
    (documentPermissionDenied || auxiliaryReadPermissionDenied ? DOCUMENT_PERMISSION_DENIED : 0) |
    (responseStatus(tasksQuery.error) === 403 ? TASK_PERMISSION_DENIED : 0) |
    (responseStatus(sourcesQuery.error) === 403 ? SOURCE_PERMISSION_DENIED : 0)
  const permissionDenied = permissionDenialMask !== 0
  const previousPermissionDenialMaskRef = useRef(permissionDenialMask)
  const permissionRecoveryQueryMaskRef = useRef(
    recoveryQueryMaskForPermissionDenials(permissionDenialMask),
  )
  const canWrite = hasWorkspaceWritePermission && !permissionDenied && !writePermissionRevoked
  const documentWriteRestrictionReasonId = permissionPending
    ? 'documents-permission-pending'
    : permissionQueryError
      ? 'documents-permission-error'
      : !canEdit || writePermissionRevoked
        ? 'documents-readonly-reason'
        : undefined
  const documentsRecoveryDescription = auxiliaryReadPermissionDenied
    ? t(($) => $['newKnowledge.documentsPermissionDescription'])
    : t(($) => $['newKnowledge.documentsErrorDescription'])
  const documentsSectionRef = useRef<HTMLElement>(null)
  const documentsTitleRef = useRef<HTMLHeadingElement>(null)
  const documentSurfaceHadFocusRef = useRef(false)
  const bulkActionsHadFocusRef = useRef(false)
  const mainRetryFocusRequestedRef = useRef(false)
  const permissionRetryButtonRef = useRef<HTMLButtonElement>(null)
  const documentsRetryButtonRef = useRef<HTMLButtonElement>(null)
  const dependencyRetryButtonRef = useRef<HTMLButtonElement>(null)
  const {
    fetchNextPage: fetchNextDocumentPage,
    hasNextPage: hasNextDocumentPage,
    isFetchNextPageError: isFetchNextDocumentPageError,
    isFetchingNextPage: isFetchingNextDocumentPage,
  } = documentsQuery
  const {
    fetchNextPage: fetchNextTaskPage,
    hasNextPage: hasNextTaskPage,
    isFetchNextPageError: isFetchNextTaskPageError,
    isFetchingNextPage: isFetchingNextTaskPage,
    refetch: refetchTasksQuery,
  } = tasksQuery
  const {
    fetchNextPage: fetchNextSourcePage,
    hasNextPage: hasNextSourcePage,
    isFetchNextPageError: isFetchNextSourcePageError,
    isFetchingNextPage: isFetchingNextSourcePage,
    refetch: refetchSourcesQuery,
  } = sourcesQuery
  const canAutoFetchDocumentPage = Boolean(
    hasNextDocumentPage && (documentsQuery.data?.pages.length ?? 0) < MAX_AUTO_CURSOR_PAGES,
  )
  const canAutoFetchTaskPage = Boolean(
    hasNextTaskPage && (tasksQuery.data?.pages.length ?? 0) < MAX_AUTO_CURSOR_PAGES,
  )
  const documents = useMemo(
    () => documentsQuery.data?.pages.flatMap((page) => page.items) ?? [],
    [documentsQuery.data],
  )
  const baseTasks = useMemo(
    () => tasksQuery.data?.pages.flatMap((page) => page.items) ?? [],
    [tasksQuery.data],
  )
  const documentIds = useMemo(() => new Set(documents.map((document) => document.id)), [documents])
  const unresolvedTaskDocumentIds = useMemo(
    () =>
      new Set(
        baseTasks.flatMap((task) => (!documentIds.has(task.documentId) ? [task.documentId] : [])),
      ),
    [baseTasks, documentIds],
  )
  const taskDataUpdateCount = useQueryDataUpdateCount(queryClient, tasksQueryOptions.queryKey)
  const taskListSnapshotRef = useRef({
    data: tasksQuery.data,
    dataUpdateCount: taskDataUpdateCount,
    dataUpdatedAt: tasksQuery.dataUpdatedAt,
  })
  const taskListGenerationRef = useRef(0)
  const [taskListGeneration, setTaskListGeneration] = useState(0)
  useLayoutEffect(() => {
    if (
      taskListSnapshotRef.current.dataUpdateCount === taskDataUpdateCount &&
      taskListSnapshotRef.current.dataUpdatedAt === tasksQuery.dataUpdatedAt &&
      taskListSnapshotRef.current.data === tasksQuery.data
    )
      return
    taskListSnapshotRef.current = {
      data: tasksQuery.data,
      dataUpdateCount: taskDataUpdateCount,
      dataUpdatedAt: tasksQuery.dataUpdatedAt,
    }
    taskListGenerationRef.current += 1
    setTaskListGeneration(taskListGenerationRef.current)
  }, [taskDataUpdateCount, tasksQuery.data, tasksQuery.dataUpdatedAt])
  const baseTaskById = useMemo(() => new Map(baseTasks.map((task) => [task.id, task])), [baseTasks])
  const sourceNames = useMemo(
    () =>
      new Map(
        (sourcesQuery.data?.pages.flatMap((page) => page.items) ?? []).map((source) => [
          source.id,
          source.name,
        ]),
      ),
    [sourcesQuery.data],
  )
  const unresolvedDocumentSourceIds = useMemo(
    () =>
      new Set(
        documents.flatMap((document) =>
          document.sourceId && !sourceNames.has(document.sourceId) ? [document.sourceId] : [],
        ),
      ),
    [documents, sourceNames],
  )
  const hasRelevantNextSourcePage = Boolean(hasNextSourcePage && unresolvedDocumentSourceIds.size)
  const isFetchingNextResultsPage = Boolean(
    isFetchingNextDocumentPage ||
    (hasNextTaskPage && isFetchingNextTaskPage) ||
    (hasRelevantNextSourcePage && isFetchingNextSourcePage),
  )
  const canAutoFetchSourcePage = Boolean(
    hasRelevantNextSourcePage && (sourcesQuery.data?.pages.length ?? 0) < MAX_AUTO_CURSOR_PAGES,
  )
  const disabledSourceIds = useMemo(
    () =>
      new Set(
        (sourcesQuery.data?.pages.flatMap((page) => page.items) ?? [])
          .filter((source) => source.status === 'disabled')
          .map((source) => source.id),
      ),
    [sourcesQuery.data],
  )
  const baseTaskByIdRef = useRef(baseTaskById)
  useLayoutEffect(() => {
    baseTaskByIdRef.current = baseTaskById
  }, [baseTaskById])
  const tasks = useMemo(
    () =>
      baseTasks.map((task) => {
        const override = taskOverrides[task.id]
        const terminalTaskPin = terminalTaskPins[task.id]
        if (
          terminalTaskPin &&
          override &&
          taskIsActive(task) &&
          !taskVersionIsAfter(task.updatedAt, terminalTaskPin.observedAt)
        )
          return { ...task, ...override }
        if (!override?.updatedAt) return override ? { ...task, ...override } : task
        if (taskVersionIsAfter(task.updatedAt, override.updatedAt)) return task
        const mergedTask = { ...task, ...override }
        if (
          !taskIsActive(task) &&
          taskIsActive(mergedTask) &&
          !taskVersionIsAfter(override.updatedAt, task.updatedAt) &&
          streamActiveOverrideVersionsRef.current.get(task.id) === override.updatedAt
        )
          return task
        return mergedTask
      }),
    [baseTasks, taskOverrides, terminalTaskPins],
  )
  const effectiveTaskById = useMemo(() => new Map(tasks.map((task) => [task.id, task])), [tasks])
  useEffect(() => {
    for (const task of tasks) {
      if (!taskIsActive(task)) {
        taskEventCursorsRef.current.delete(task.id)
        streamActiveOverrideVersionsRef.current.delete(task.id)
        trustedActiveOverrideVersionsRef.current.delete(task.id)
        trustedOverrideListGenerationsRef.current.delete(task.id)
      }
    }
  }, [tasks])

  useEffect(() => {
    const clearedActiveTaskIds: string[] = []
    for (const task of baseTasks) {
      const denial = terminalConfirmableAuxiliaryDenialsRef.current.get(task.id)
      if (!denial || taskListGeneration <= denial.taskListGeneration) continue
      if (taskIsActive(task)) {
        if (!taskVersionIsAfter(task.updatedAt, denial.taskVersion)) continue
        auxiliaryTaskReadGuard.clearTask(task.id)
        terminalConfirmableAuxiliaryDenialsRef.current.delete(task.id)
        continue
      }
      if (!auxiliaryTaskReadGuard.clearThrough(task.id, task.updatedAt)) continue
      terminalConfirmableAuxiliaryDenialsRef.current.delete(task.id)
      const effectiveTask = effectiveTaskById.get(task.id)
      if (effectiveTask && taskIsActive(effectiveTask)) clearedActiveTaskIds.push(task.id)
    }
    if (!clearedActiveTaskIds.length) return
    // oxlint-disable-next-line eslint-react/set-state-in-effect -- Clearing a committed terminal guard must remount effective active observers.
    setTaskObserverGenerations((current) => {
      const next = { ...current }
      for (const taskId of clearedActiveTaskIds) next[taskId] = (next[taskId] ?? 0) + 1
      return next
    })
  }, [auxiliaryTaskReadGuard, baseTasks, effectiveTaskById, taskListGeneration])
  const currentTaskStateRef = useRef(new Map(tasks.map((task) => [task.id, task.state])))
  const currentTaskVersionRef = useRef(new Map(tasks.map((task) => [task.id, task.updatedAt])))
  useLayoutEffect(() => {
    const currentTaskIds = new Set(tasks.map((task) => task.id))
    for (const task of tasks) {
      const currentVersion = currentTaskVersionRef.current.get(task.id)
      if (!currentVersion || !taskVersionIsAfter(currentVersion, task.updatedAt)) {
        currentTaskStateRef.current.set(task.id, task.state)
        currentTaskVersionRef.current.set(task.id, task.updatedAt)
      }
    }
    for (const taskId of currentTaskVersionRef.current.keys()) {
      if (currentTaskIds.has(taskId)) continue
      currentTaskStateRef.current.delete(taskId)
      currentTaskVersionRef.current.delete(taskId)
    }
  }, [tasks])

  const taskByDocument = useMemo(() => newestTaskByDocument(tasks), [tasks])
  const documentStatuses = useMemo(
    () =>
      new Map(
        documents.map((document) => [
          document.id,
          documentDisplayStatus(
            document,
            taskByDocument.get(document.id),
            Boolean(
              document.sourceId &&
              (disabledSourceIds.has(document.sourceId) ||
                (!hasNextSourcePage &&
                  !sourcesQuery.error &&
                  !sourcesQuery.isFetchNextPageError &&
                  !sourceNames.has(document.sourceId))),
            ),
          ),
        ]),
      ),
    [
      disabledSourceIds,
      documents,
      hasNextSourcePage,
      sourceNames,
      sourcesQuery.error,
      sourcesQuery.isFetchNextPageError,
      taskByDocument,
    ],
  )
  const filterActive = filter !== 'all' || Boolean(search.trim())
  const statusFilterActive = filter !== 'all'
  const availableDocumentIds = useMemo(
    () =>
      new Set(
        documents
          .filter((document) => documentStatuses.get(document.id) !== 'disabled')
          .map((document) => document.id),
      ),
    [documents, documentStatuses],
  )
  const validSelectedDocumentIds = useMemo(
    () =>
      new Set(
        [...selectedDocumentIds].filter((documentId) => availableDocumentIds.has(documentId)),
      ),
    [availableDocumentIds, selectedDocumentIds],
  )
  const filteredDocuments = useMemo(() => {
    const normalizedSearch = search.trim().toLocaleLowerCase()
    return documents.filter((document) => {
      const status = documentStatuses.get(document.id)
      if (filter !== 'all' && status !== filter) return false
      if (!normalizedSearch) return true
      const resolvedSourceName =
        (document.sourceId && sourceNames.get(document.sourceId)) ?? sourceName(document)
      return `${document.title} ${resolvedSourceName ?? ''}`
        .toLocaleLowerCase()
        .includes(normalizedSearch)
    })
  }, [documentStatuses, documents, filter, search, sourceNames])
  const completingFilteredResults =
    filterActive &&
    !documentsQuery.isFetchNextPageError &&
    (canAutoFetchDocumentPage || documentsQuery.isFetchingNextPage)
  const filteredResultsIncomplete = Boolean(
    (filterActive &&
      (hasNextDocumentPage ||
        documentsQuery.isFetchingNextPage ||
        documentsQuery.isFetchNextPageError)) ||
    (statusFilterActive &&
      (hasNextTaskPage || tasksQuery.isFetchingNextPage || tasksQuery.isFetchNextPageError)) ||
    (filterActive &&
      unresolvedDocumentSourceIds.size > 0 &&
      (hasNextSourcePage || sourcesQuery.isFetchingNextPage || sourcesQuery.isFetchNextPageError)),
  )
  const taskQueryBlockingError = Boolean(
    !tasksQuery.data && (tasksQuery.error || blockingDependencyRetries.tasks),
  )
  const sourceQueryBlockingError = Boolean(
    !sourcesQuery.data && (sourcesQuery.error || blockingDependencyRetries.sources),
  )
  const dependencyQueryBlockingError = taskQueryBlockingError || sourceQueryBlockingError
  const dependencyQueryWarning = Boolean(
    (tasksQuery.error && tasksQuery.data) ||
    tasksQuery.isFetchNextPageError ||
    (sourcesQuery.error && sourcesQuery.data) ||
    sourcesQuery.isFetchNextPageError,
  )
  const taskResultsIncomplete = Boolean(
    !tasksQuery.data || tasksQuery.isPending || tasksQuery.isFetchingNextPage,
  )
  const sourceResultsIncomplete = Boolean(
    !sourcesQuery.data ||
    sourcesQuery.isPending ||
    (unresolvedDocumentSourceIds.size &&
      (hasNextSourcePage ||
        sourcesQuery.error ||
        sourcesQuery.isFetchingNextPage ||
        sourcesQuery.isFetchNextPageError)),
  )
  const sourceQueryWarning = Boolean(
    (sourcesQuery.error && sourcesQuery.data) || sourcesQuery.isFetchNextPageError,
  )
  const taskQueryWarning = Boolean(
    (tasksQuery.error && tasksQuery.data) || tasksQuery.isFetchNextPageError,
  )
  const documentQueryWarning = Boolean(documentsQuery.error && documentsQuery.data)
  const dependencyRetryFetching = Boolean(
    (taskQueryWarning && tasksQuery.isFetching) || (sourceQueryWarning && sourcesQuery.isFetching),
  )
  const blockingDependencyRetryFetching = Boolean(
    (taskQueryBlockingError && tasksQuery.isFetching) ||
    (sourceQueryBlockingError && sourcesQuery.isFetching),
  )
  const mainRecoveryVisible = Boolean(
    permissionQueryError ||
    documentsQuery.error ||
    dependencyQueryBlockingError ||
    dependencyQueryWarning,
  )
  const mainRecoveryIdentity = [
    permissionQueryError ? 'permission' : '',
    documentsQuery.error ? 'documents' : '',
    taskQueryBlockingError ? 'tasks-blocking' : '',
    sourceQueryBlockingError ? 'sources-blocking' : '',
    taskQueryWarning ? 'tasks-warning' : '',
    sourceQueryWarning ? 'sources-warning' : '',
  ].join(':')
  const dependencyResultsIncomplete = taskResultsIncomplete || sourceResultsIncomplete
  const selectionDisabled =
    !canWrite ||
    dependencyResultsIncomplete ||
    documentQueryWarning ||
    taskQueryWarning ||
    (sourceQueryWarning && unresolvedDocumentSourceIds.size > 0) ||
    filteredResultsIncomplete
  const reindexUnavailableReason =
    tasksQuery.error || tasksQuery.isFetchNextPageError
      ? t(($) => $['newKnowledge.tasksErrorDescription'])
      : (sourcesQuery.error || sourcesQuery.isFetchNextPageError) &&
          unresolvedDocumentSourceIds.size > 0
        ? t(($) => $['newKnowledge.sourcesErrorDescription'])
        : documentsQuery.error || documentsQuery.isFetchNextPageError
          ? t(($) => $['newKnowledge.documentsErrorDescription'])
          : dependencyResultsIncomplete
            ? tCommon(($) => $.loading)
            : filteredResultsIncomplete
              ? t(($) => $['newKnowledge.partialDocumentResults'])
              : undefined
  const selectableFilteredDocuments = filteredDocuments.filter(
    (document) => documentStatuses.get(document.id) !== 'disabled',
  )
  const attentionTasks = tasks.filter(taskNeedsAttention)
  const hasTaskError = attentionTasks.some(
    (task) => task.state === 'failed' || task.state === 'canceled',
  )
  const activeTasks = useMemo(() => tasks.filter(taskIsActive), [tasks])
  const orderedActiveTasks = useMemo(
    () =>
      [...activeTasks].sort(
        (left, right) =>
          left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id),
      ),
    [activeTasks],
  )
  const taskObserverVersion = (task: DocumentProcessingTask) => {
    let latestVersion = task.updatedAt
    for (const candidate of [
      currentTaskVersionRef.current.get(task.id),
      taskProgressStore.get(task.id)?.updatedAt,
    ]) {
      if (candidate && taskVersionIsAfter(candidate, latestVersion)) latestVersion = candidate
    }
    return latestVersion
  }
  const streamedActiveTasks = (() => {
    if (permissionDenied) return []
    const streamableActiveTasks = orderedActiveTasks.filter(
      (task) => !auxiliaryTaskReadGuard.isBlocked(task.id, taskObserverVersion(task)),
    )
    const streamCount = Math.min(MAX_TASK_EVENT_STREAMS, streamableActiveTasks.length)
    if (!streamCount) return []
    const offset = taskStreamOffset % streamableActiveTasks.length
    return Array.from(
      { length: streamCount },
      (_, index) => streamableActiveTasks[(offset + index) % streamableActiveTasks.length]!,
    )
  })()
  const blockedActiveTaskSignature = orderedActiveTasks
    .map((task) => [task.id, taskObserverVersion(task)] as const)
    .filter(([taskId, taskVersion]) => auxiliaryTaskReadGuard.isBlocked(taskId, taskVersion))
    .map(([taskId, taskVersion]) => `${taskId}:${taskVersion}`)
    .join('|')
  const orderedFailedTasks = useMemo(
    () =>
      tasks
        .filter((task) => task.state === 'failed')
        .sort((left, right) => {
          if (taskVersionIsAfter(left.updatedAt, right.updatedAt)) return -1
          if (taskVersionIsAfter(right.updatedAt, left.updatedAt)) return 1
          return right.id.localeCompare(left.id)
        }),
    [tasks],
  )
  const orderedFailedTasksRef = useRef(orderedFailedTasks)
  useLayoutEffect(() => {
    orderedFailedTasksRef.current = orderedFailedTasks
  }, [orderedFailedTasks])
  const failedTaskPollSignature = orderedFailedTasks
    .map((task) => `${task.id}:${task.updatedAt}`)
    .join('|')
  const incompleteTaskHistoryHint = hasNextTaskPage
    ? ` · ${t(($) => $['newKnowledge.taskHistoryIncomplete'])}`
    : ''
  const attentionTaskBadge =
    attentionTasks.length || hasNextTaskPage
      ? `${attentionTasks.length}${hasNextTaskPage ? '+' : ''}`
      : undefined
  const tasksButtonLabel = `${
    attentionTasks.length || hasNextTaskPage
      ? t(($) => $['newKnowledge.tasksWithAttention'], { count: attentionTasks.length })
      : t(($) => $['newKnowledge.tasks'])
  }${incompleteTaskHistoryHint}`
  const tasksLiveStatus = `${
    hasTaskError
      ? t(($) => $['newKnowledge.taskAttentionErrorCount'], { count: attentionTasks.length })
      : attentionTasks.length || hasNextTaskPage
        ? t(($) => $['newKnowledge.taskAttentionCount'], { count: attentionTasks.length })
        : t(($) => $['newKnowledge.taskAttentionClear'])
  }${incompleteTaskHistoryHint}`
  const allFilteredSelected =
    selectableFilteredDocuments.length > 0 &&
    selectableFilteredDocuments.every((document) => validSelectedDocumentIds.has(document.id))
  const someFilteredSelected = selectableFilteredDocuments.some((document) =>
    validSelectedDocumentIds.has(document.id),
  )
  const bulkActionsVisible = canWrite && validSelectedDocumentIds.size > 0
  const previousBulkActionsVisibleRef = useRef(bulkActionsVisible)

  useLayoutEffect(() => {
    const wasVisible = previousBulkActionsVisibleRef.current
    previousBulkActionsVisibleRef.current = bulkActionsVisible
    if (!wasVisible || bulkActionsVisible || !bulkActionsHadFocusRef.current) return
    if (permissionDenied) return
    bulkActionsHadFocusRef.current = false
    documentsTitleRef.current?.focus()
  }, [bulkActionsVisible, permissionDenied])

  useEffect(() => {
    if (permissionDenied || orderedActiveTasks.length <= MAX_TASK_EVENT_STREAMS) return
    const interval = window.setInterval(
      () => setTaskStreamOffset((current) => current + MAX_TASK_EVENT_STREAMS),
      5000,
    )
    return () => window.clearInterval(interval)
  }, [orderedActiveTasks.length, permissionDenied])

  useEffect(() => {
    if (permissionDenied || !blockedActiveTaskSignature) return
    let canceled = false
    let refreshInterval = BLOCKED_ACTIVE_TASK_REFRESH_INTERVAL
    let timeout: number | undefined
    const refreshBlockedTasks = async () => {
      if (canceled) return
      await refetchTasksQuery({ cancelRefetch: false }).catch(() => undefined)
      if (canceled) return
      refreshInterval = Math.min(refreshInterval * 2, MAX_BLOCKED_ACTIVE_TASK_REFRESH_INTERVAL)
      timeout = window.setTimeout(refreshBlockedTasks, refreshInterval)
    }
    timeout = window.setTimeout(refreshBlockedTasks, BLOCKED_ACTIVE_TASK_REFRESH_INTERVAL)
    return () => {
      canceled = true
      if (timeout !== undefined) window.clearTimeout(timeout)
    }
  }, [blockedActiveTaskSignature, permissionDenied, refetchTasksQuery])

  useLayoutEffect(() => {
    if (!writePermissionRevoked || !writePermissionFocusRecoveryRequestedRef.current) return
    writePermissionFocusRecoveryRequestedRef.current = false
    writePermissionFocusOriginRef.current = null
    documentsTitleRef.current?.focus()
  }, [writePermissionRevoked])

  useEffect(() => {
    const previousPermissionDenialMask = previousPermissionDenialMaskRef.current
    previousPermissionDenialMaskRef.current = permissionDenialMask
    const addedPermissionDenials = permissionDenialMask & ~previousPermissionDenialMask
    let recoveryQueryMask =
      permissionRecoveryQueryMaskRef.current |
      recoveryQueryMaskForPermissionDenials(addedPermissionDenials)
    if (
      previousPermissionDenialMask & TASK_PERMISSION_DENIED &&
      !(permissionDenialMask & TASK_PERMISSION_DENIED)
    )
      recoveryQueryMask &= ~TASK_PERMISSION_DENIED
    if (
      previousPermissionDenialMask & SOURCE_PERMISSION_DENIED &&
      !(permissionDenialMask & SOURCE_PERMISSION_DENIED)
    )
      recoveryQueryMask &= ~SOURCE_PERMISSION_DENIED
    recoveryQueryMask &= ~permissionDenialMask
    permissionRecoveryQueryMaskRef.current = recoveryQueryMask
    if (previousPermissionDenialMask && !permissionDenied) {
      blockedFailedTaskPollVersionsRef.current.clear()
      if (recoveryQueryMask & TASK_PERMISSION_DENIED)
        void refetchTasksQuery({ cancelRefetch: false })
      if (recoveryQueryMask & SOURCE_PERMISSION_DENIED)
        void refetchSourcesQuery({ cancelRefetch: false })
      permissionRecoveryQueryMaskRef.current = 0
      if (documentSurfaceHadFocusRef.current || bulkActionsHadFocusRef.current)
        documentsTitleRef.current?.focus()
      bulkActionsHadFocusRef.current = false
      return
    }
    if (previousPermissionDenialMask || !permissionDenied) return
    const shouldRestoreFocus =
      tasksOpen || documentSurfaceHadFocusRef.current || bulkActionsHadFocusRef.current
    if (tasksOpen) {
      // oxlint-disable-next-line eslint-react/set-state-in-effect -- Permission revocation permanently closes the controlled task drawer.
      setTasksOpen(false)
    }
    if (shouldRestoreFocus) documentPermissionAlertRef.current?.focus()
    bulkActionsHadFocusRef.current = false
  }, [permissionDenialMask, permissionDenied, refetchSourcesQuery, refetchTasksQuery, tasksOpen])

  useEffect(() => {
    if (
      !writePermissionRevoked ||
      writePermissionRecoveryGeneration !== writePermissionDenialGenerationRef.current
    ) {
      writePermissionRecoveryFetchSeenRef.current = false
      return
    }
    if (workspacePermissionKeysFetching) {
      writePermissionRecoveryFetchSeenRef.current = true
      return
    }
    if (
      !writePermissionRecoveryFetchSeenRef.current ||
      permissionPending ||
      permissionQueryError ||
      !canEdit
    )
      return
    writePermissionRecoveryFetchSeenRef.current = false
    // oxlint-disable-next-line eslint-react/set-state-in-effect -- A post-denial permission request is the authoritative event that retires the local mutation lock.
    setWritePermissionRevoked(false)
    // oxlint-disable-next-line eslint-react/set-state-in-effect -- The completed recovery generation is retired with its write lock.
    setWritePermissionRecoveryGeneration(undefined)
  }, [
    canEdit,
    permissionPending,
    permissionQueryError,
    workspacePermissionKeysFetching,
    writePermissionRecoveryGeneration,
    writePermissionRevoked,
  ])

  useEffect(() => {
    if (!mainRetryFocusRequestedRef.current) return
    if (mainRecoveryVisible) {
      if (documentPermissionDenied) {
        mainRetryFocusRequestedRef.current = false
        documentPermissionAlertRef.current?.focus()
      } else if (permissionQueryError) permissionRetryButtonRef.current?.focus()
      else if (documentsQuery.error && !permissionDenied) documentsRetryButtonRef.current?.focus()
      else dependencyRetryButtonRef.current?.focus()
      return
    }
    mainRetryFocusRequestedRef.current = false
    documentsTitleRef.current?.focus()
  }, [
    documentsQuery.error,
    documentPermissionDenied,
    mainRecoveryIdentity,
    mainRecoveryVisible,
    permissionDenied,
    permissionQueryError,
  ])

  useEffect(() => {
    if (!blockingDependencyRetries.tasks && !blockingDependencyRetries.sources) return
    if (
      (!blockingDependencyRetries.tasks || !tasksQuery.data) &&
      (!blockingDependencyRetries.sources || !sourcesQuery.data)
    )
      return
    // oxlint-disable-next-line eslint-react/set-state-in-effect -- Successful first-page retries retire the locally stabilized blocking state.
    setBlockingDependencyRetries((current) => ({
      sources: current.sources && !sourcesQuery.data,
      tasks: current.tasks && !tasksQuery.data,
    }))
  }, [blockingDependencyRetries, sourcesQuery.data, tasksQuery.data])

  useEffect(() => {
    if (
      !permissionDenied &&
      (filterActive || (tasksOpen && unresolvedTaskDocumentIds.size > 0)) &&
      canAutoFetchDocumentPage &&
      !isFetchingNextDocumentPage &&
      !isFetchNextDocumentPageError
    )
      void fetchNextDocumentPage()
  }, [
    fetchNextDocumentPage,
    filterActive,
    tasksOpen,
    unresolvedTaskDocumentIds,
    canAutoFetchDocumentPage,
    isFetchNextDocumentPageError,
    isFetchingNextDocumentPage,
    permissionDenied,
  ])

  useEffect(() => {
    if (
      !permissionDenied &&
      canAutoFetchTaskPage &&
      !isFetchingNextTaskPage &&
      !isFetchNextTaskPageError
    )
      void fetchNextTaskPage()
  }, [
    canAutoFetchTaskPage,
    fetchNextTaskPage,
    isFetchNextTaskPageError,
    isFetchingNextTaskPage,
    permissionDenied,
  ])

  useEffect(() => {
    if (
      !permissionDenied &&
      canAutoFetchSourcePage &&
      !isFetchingNextSourcePage &&
      !isFetchNextSourcePageError
    )
      void fetchNextSourcePage()
  }, [
    canAutoFetchSourcePage,
    fetchNextSourcePage,
    isFetchNextSourcePageError,
    isFetchingNextSourcePage,
    permissionDenied,
  ])

  const refreshDocuments = useCallback(() => {
    void queryClient.invalidateQueries({
      predicate: (query) => queryKeyMatchesKnowledgeSpace(query.queryKey, knowledgeSpaceId),
      queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdLogicalDocuments.key(),
    })
  }, [knowledgeSpaceId, queryClient])

  const refreshDocumentsAndTasks = useCallback(() => {
    void Promise.allSettled([
      queryClient.invalidateQueries({
        predicate: (query) => queryKeyMatchesKnowledgeSpace(query.queryKey, knowledgeSpaceId),
        queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdLogicalDocuments.key(),
      }),
      queryClient.invalidateQueries({
        predicate: (query) => queryKeyMatchesKnowledgeSpace(query.queryKey, knowledgeSpaceId),
        queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdProcessingTasks.key(),
      }),
    ])
  }, [knowledgeSpaceId, queryClient])

  const refreshWorkspacePermissions = useCallback(
    async (releaseWriteLockOnSuccess: boolean) => {
      const denialGeneration = writePermissionDenialGenerationRef.current
      const result = await (releaseWriteLockOnSuccess && writePermissionRevoked
        ? refreshWorkspacePermissionKeysAfterMutationDenial()
        : retryWorkspacePermissionKeys())
      const refreshedPermissionKeys = result.data?.dataset?.default_permission_keys
      if (
        releaseWriteLockOnSuccess &&
        writePermissionDenialGenerationRef.current === denialGeneration &&
        !result.error &&
        refreshedPermissionKeys &&
        hasPermission(refreshedPermissionKeys, DatasetACLPermission.Edit)
      ) {
        writePermissionRecoveryFetchSeenRef.current = false
        setWritePermissionRevoked(false)
        setWritePermissionRecoveryGeneration(undefined)
      }
    },
    [
      refreshWorkspacePermissionKeysAfterMutationDenial,
      retryWorkspacePermissionKeys,
      writePermissionRevoked,
    ],
  )

  const handleWritePermissionDenied = useCallback(() => {
    const denialGeneration = writePermissionDenialGenerationRef.current + 1
    writePermissionDenialGenerationRef.current = denialGeneration
    writePermissionRecoveryFetchSeenRef.current = false
    setWritePermissionRecoveryGeneration(undefined)
    setWritePermissionRevoked(true)
    void refreshWorkspacePermissionKeysAfterMutationDenial().then((result) => {
      const refreshedPermissionKeys = result.data?.dataset?.default_permission_keys
      if (writePermissionDenialGenerationRef.current !== denialGeneration) return
      if (
        !result.error &&
        refreshedPermissionKeys &&
        hasPermission(refreshedPermissionKeys, DatasetACLPermission.Edit)
      ) {
        writePermissionRecoveryFetchSeenRef.current = false
        setWritePermissionRevoked(false)
        setWritePermissionRecoveryGeneration(undefined)
        return
      }
      setWritePermissionRecoveryGeneration(denialGeneration)
    })
  }, [refreshWorkspacePermissionKeysAfterMutationDenial])

  const reconcileTerminalTask = useCallback(
    async function reconcileTerminalTaskRequest(
      taskId: string,
      terminalVersion: string,
      reconciliationGeneration: number,
      retryAttempt = 0,
    ) {
      const currentTask = baseTaskByIdRef.current.get(taskId)
      if (!currentTask || auxiliaryTaskReadGuard.isBlocked(taskId, terminalVersion)) return
      const pendingRetryTimeout = terminalReconciliationTimeoutsRef.current.get(taskId)
      if (pendingRetryTimeout !== undefined) window.clearTimeout(pendingRetryTimeout)
      terminalReconciliationTimeoutsRef.current.delete(taskId)
      terminalReconciliationControllersRef.current.get(taskId)?.abort()
      const controller = new AbortController()
      terminalReconciliationControllersRef.current.set(taskId, controller)
      const requestTimeout = window.setTimeout(
        () => controller.abort(),
        TERMINAL_RECONCILIATION_REQUEST_TIMEOUT,
      )
      try {
        const snapshot =
          await consoleClient.knowledgeFs.getKnowledgeSpacesByIdDocumentsByDocumentIdProcessingTasksByTaskId(
            {
              params: {
                documentId: currentTask.documentId,
                id: knowledgeSpaceId,
                taskId,
              },
            },
            { signal: controller.signal },
          )
        if (
          terminalReconciliationControllersRef.current.get(taskId) !== controller ||
          terminalReconciliationGenerationsRef.current.get(taskId) !== reconciliationGeneration
        )
          return
        terminalReconciliationControllersRef.current.delete(taskId)
        const currentTaskVersion = currentTaskVersionRef.current.get(taskId)
        if (currentTaskVersion && taskVersionIsAfter(currentTaskVersion, snapshot.updatedAt)) return
        if (taskVersionIsAfter(terminalVersion, snapshot.updatedAt)) return
        auxiliaryTaskReadGuard.clearTask(taskId)
        failedPollAuxiliaryDenialsRef.current.delete(taskId)
        terminalConfirmableAuxiliaryDenialsRef.current.delete(taskId)
        const normalizedSnapshot = normalizedTaskSnapshot(snapshot)
        if (taskIsActive(snapshot))
          trustedActiveOverrideVersionsRef.current.set(taskId, {
            taskListGeneration: taskListGenerationRef.current,
            updatedAt: snapshot.updatedAt,
          })
        else trustedActiveOverrideVersionsRef.current.delete(taskId)
        taskProgressStore.delete(taskId)
        currentTaskStateRef.current.set(taskId, snapshot.state)
        currentTaskVersionRef.current.set(taskId, snapshot.updatedAt)
        setTaskOverrides((current) => {
          const currentVersion = current[taskId]?.updatedAt
          if (currentVersion && taskVersionIsAfter(currentVersion, snapshot.updatedAt))
            return current
          return { ...current, [taskId]: normalizedSnapshot }
        })
        if (taskIsActive(snapshot)) {
          blockedFailedTaskPollVersionsRef.current.delete(taskId)
          taskEventCursorsRef.current.delete(taskId)
          const pollGeneration = failedTaskPollGenerationsRef.current.get(taskId) ?? 0
          failedTaskPollGenerationsRef.current.set(taskId, pollGeneration + 1)
          setTerminalTaskPins((current) => {
            const pin = current[taskId]
            if (!pin || taskVersionIsAfter(pin.observedAt, snapshot.updatedAt)) return current
            const next = { ...current }
            delete next[taskId]
            return next
          })
          setTaskObserverGenerations((current) => ({
            ...current,
            [taskId]: (current[taskId] ?? 0) + 1,
          }))
        }
      } catch (error) {
        if (terminalReconciliationControllersRef.current.get(taskId) !== controller) return
        terminalReconciliationControllersRef.current.delete(taskId)
        if (responseStatus(error) === 403) {
          const currentTaskVersion = currentTaskVersionRef.current.get(taskId)
          const deniedVersion =
            currentTaskVersion && taskVersionIsAfter(currentTaskVersion, terminalVersion)
              ? currentTaskVersion
              : terminalVersion
          terminalConfirmableAuxiliaryDenialsRef.current.set(taskId, {
            taskListGeneration: taskListGenerationRef.current,
            taskVersion: deniedVersion,
          })
          denyAuxiliaryTaskRead(taskId, deniedVersion)
          return
        }
        if (
          retryAttempt >= 4 ||
          !taskSnapshotErrorIsTransient(error) ||
          terminalReconciliationGenerationsRef.current.get(taskId) !== reconciliationGeneration
        )
          return
        const timeout = window.setTimeout(
          () => {
            terminalReconciliationTimeoutsRef.current.delete(taskId)
            if (
              terminalReconciliationGenerationsRef.current.get(taskId) === reconciliationGeneration
            )
              void reconcileTerminalTaskRequest(
                taskId,
                terminalVersion,
                reconciliationGeneration,
                retryAttempt + 1,
              )
          },
          Math.min(1000 * 2 ** retryAttempt, 30000),
        )
        terminalReconciliationTimeoutsRef.current.set(taskId, timeout)
      } finally {
        window.clearTimeout(requestTimeout)
      }
    },
    [auxiliaryTaskReadGuard, denyAuxiliaryTaskRead, knowledgeSpaceId, taskProgressStore],
  )

  useEffect(() => {
    if (permissionDenied) return
    for (const task of baseTasks) {
      if (taskIsActive(task)) continue
      const override = taskOverrides[task.id]
      const trustedOverride = trustedActiveOverrideVersionsRef.current.get(task.id)
      if (
        !override?.updatedAt ||
        !taskIsActive({ ...task, ...override }) ||
        taskVersionIsAfter(override.updatedAt, task.updatedAt) ||
        trustedOverride?.updatedAt !== override.updatedAt ||
        taskListGeneration <= trustedOverride.taskListGeneration ||
        trustedOverrideListGenerationsRef.current.get(task.id) === taskListGeneration
      )
        continue
      trustedOverrideListGenerationsRef.current.set(task.id, taskListGeneration)
      const reconciliationGeneration =
        (terminalReconciliationGenerationsRef.current.get(task.id) ?? 0) + 1
      terminalReconciliationGenerationsRef.current.set(task.id, reconciliationGeneration)
      void reconcileTerminalTask(task.id, task.updatedAt, reconciliationGeneration)
    }
  }, [baseTasks, permissionDenied, reconcileTerminalTask, taskListGeneration, taskOverrides])

  useEffect(
    () => () => {
      for (const controller of terminalReconciliationControllersRef.current.values())
        controller.abort()
      terminalReconciliationControllersRef.current.clear()
      for (const timeout of terminalReconciliationTimeoutsRef.current.values())
        window.clearTimeout(timeout)
      terminalReconciliationTimeoutsRef.current.clear()
    },
    [knowledgeSpaceId],
  )

  useEffect(() => {
    if (!permissionDenied) return
    void queryClient.cancelQueries({
      predicate: (query) => queryKeyMatchesKnowledgeSpace(query.queryKey, knowledgeSpaceId),
      queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdProcessingTasks.key(),
    })
    void queryClient.cancelQueries({
      predicate: (query) => queryKeyMatchesKnowledgeSpace(query.queryKey, knowledgeSpaceId),
      queryKey: consoleQuery.knowledgeFs.getKnowledgeSpacesByIdSources.key(),
    })
    for (const [taskId, controller] of terminalReconciliationControllersRef.current) {
      controller.abort()
      terminalReconciliationControllersRef.current.delete(taskId)
      const generation = terminalReconciliationGenerationsRef.current.get(taskId) ?? 0
      terminalReconciliationGenerationsRef.current.set(taskId, generation + 1)
    }
    for (const timeout of terminalReconciliationTimeoutsRef.current.values())
      window.clearTimeout(timeout)
    terminalReconciliationTimeoutsRef.current.clear()
    equalRetryListGenerationsRef.current.clear()
  }, [knowledgeSpaceId, permissionDenied, queryClient])

  useEffect(() => {
    const taskIds = new Set(baseTasks.map((task) => task.id))
    const pruneMap = (map: Map<string, unknown>) => {
      for (const taskId of map.keys()) {
        if (!taskIds.has(taskId)) map.delete(taskId)
      }
    }

    for (const [taskId, controller] of terminalReconciliationControllersRef.current) {
      if (taskIds.has(taskId)) continue
      controller.abort()
      terminalReconciliationControllersRef.current.delete(taskId)
    }
    for (const [taskId, timeout] of terminalReconciliationTimeoutsRef.current) {
      if (taskIds.has(taskId)) continue
      window.clearTimeout(timeout)
      terminalReconciliationTimeoutsRef.current.delete(taskId)
    }
    pruneMap(terminalReconciliationGenerationsRef.current)
    pruneMap(failedTaskPollGenerationsRef.current)
    pruneMap(blockedFailedTaskPollVersionsRef.current)
    pruneMap(failedPollAuxiliaryDenialsRef.current)
    pruneMap(terminalConfirmableAuxiliaryDenialsRef.current)
    auxiliaryTaskReadGuard.retain(taskIds)
    pruneMap(equalRetryListGenerationsRef.current)
    pruneMap(pendingTerminalProgressRef.current)
    pruneMap(taskEventCursorsRef.current)
    pruneMap(trustedOverrideListGenerationsRef.current)
    for (const map of [
      streamActiveOverrideVersionsRef.current,
      trustedActiveOverrideVersionsRef.current,
    ]) {
      for (const taskId of map.keys()) {
        if (!taskIds.has(taskId)) map.delete(taskId)
      }
    }
    taskProgressStore.retain(taskIds)

    const retainTaskState = <Value,>(current: Record<string, Value>) => {
      const staleTaskIds = Object.keys(current).filter((taskId) => !taskIds.has(taskId))
      if (!staleTaskIds.length) return current
      const next = { ...current }
      for (const taskId of staleTaskIds) delete next[taskId]
      return next
    }
    // oxlint-disable-next-line eslint-react/set-state-in-effect -- Prune state for tasks removed by a refreshed cursor result.
    setTaskOverrides(retainTaskState)
    // oxlint-disable-next-line eslint-react/set-state-in-effect -- Prune state for tasks removed by a refreshed cursor result.
    setTerminalTaskPins(retainTaskState)
    // oxlint-disable-next-line eslint-react/set-state-in-effect -- Prune state for tasks removed by a refreshed cursor result.
    setTaskObserverGenerations(retainTaskState)
  }, [auxiliaryTaskReadGuard, baseTasks, taskProgressStore])

  useEffect(() => {
    if (permissionDenied) return
    const strictRetries = new Map<string, DocumentProcessingTask>()
    const equalTimestampRetries = new Map<string, TerminalTaskPin>()
    const confirmedTerminals = new Map<string, DocumentProcessingTask>()
    for (const task of baseTasks) {
      const pin = terminalTaskPins[task.id]
      if (!pin || taskListGeneration <= pin.taskListGeneration) continue
      if (!taskIsActive(task)) {
        if (!taskVersionIsAfter(pin.observedAt, task.updatedAt))
          confirmedTerminals.set(task.id, task)
        continue
      }
      if (taskVersionIsAfter(task.updatedAt, pin.observedAt)) strictRetries.set(task.id, task)
      else if (!taskVersionIsAfter(pin.observedAt, task.updatedAt))
        equalTimestampRetries.set(task.id, pin)
    }

    for (const taskId of confirmedTerminals.keys()) {
      const generation = terminalReconciliationGenerationsRef.current.get(taskId) ?? 0
      terminalReconciliationGenerationsRef.current.set(taskId, generation + 1)
      terminalReconciliationControllersRef.current.get(taskId)?.abort()
      terminalReconciliationControllersRef.current.delete(taskId)
      const timeout = terminalReconciliationTimeoutsRef.current.get(taskId)
      if (timeout !== undefined) window.clearTimeout(timeout)
      terminalReconciliationTimeoutsRef.current.delete(taskId)
    }
    if (confirmedTerminals.size) {
      // oxlint-disable-next-line eslint-react/set-state-in-effect -- A current terminal list snapshot supersedes the partial SSE terminal payload.
      setTerminalTaskPins((current) => {
        const next = { ...current }
        for (const taskId of confirmedTerminals.keys()) delete next[taskId]
        return next
      })
      // oxlint-disable-next-line eslint-react/set-state-in-effect -- Restore complete server error details from the authoritative terminal list snapshot.
      setTaskOverrides((current) => {
        const next = { ...current }
        for (const [taskId, task] of confirmedTerminals) {
          const overrideVersion = current[taskId]?.updatedAt
          if (!overrideVersion || !taskVersionIsAfter(overrideVersion, task.updatedAt))
            delete next[taskId]
        }
        return next
      })
    }

    for (const taskId of strictRetries.keys()) {
      taskProgressStore.delete(taskId)
      blockedFailedTaskPollVersionsRef.current.delete(taskId)
      auxiliaryTaskReadGuard.clearTask(taskId)
      failedPollAuxiliaryDenialsRef.current.delete(taskId)
      terminalConfirmableAuxiliaryDenialsRef.current.delete(taskId)
      taskEventCursorsRef.current.delete(taskId)
      const pollGeneration = failedTaskPollGenerationsRef.current.get(taskId) ?? 0
      failedTaskPollGenerationsRef.current.set(taskId, pollGeneration + 1)
      const generation = terminalReconciliationGenerationsRef.current.get(taskId) ?? 0
      terminalReconciliationGenerationsRef.current.set(taskId, generation + 1)
      terminalReconciliationControllersRef.current.get(taskId)?.abort()
      terminalReconciliationControllersRef.current.delete(taskId)
      const timeout = terminalReconciliationTimeoutsRef.current.get(taskId)
      if (timeout !== undefined) window.clearTimeout(timeout)
      terminalReconciliationTimeoutsRef.current.delete(taskId)
    }
    if (strictRetries.size) {
      // oxlint-disable-next-line eslint-react/set-state-in-effect -- A strictly newer active list snapshot proves a retry without another request.
      setTerminalTaskPins((current) => {
        const next = { ...current }
        for (const taskId of strictRetries.keys()) delete next[taskId]
        return next
      })
      // oxlint-disable-next-line eslint-react/set-state-in-effect -- Drop terminal overrides only after a strictly newer active list snapshot.
      setTaskOverrides((current) => {
        const next = { ...current }
        for (const [taskId, task] of strictRetries) {
          const overrideVersion = current[taskId]?.updatedAt
          if (!overrideVersion || !taskVersionIsAfter(overrideVersion, task.updatedAt))
            delete next[taskId]
        }
        return next
      })
    }

    for (const [taskId, pin] of equalTimestampRetries) {
      if (equalRetryListGenerationsRef.current.get(taskId) === taskListGeneration) continue
      equalRetryListGenerationsRef.current.set(taskId, taskListGeneration)
      auxiliaryTaskReadGuard.clearTask(taskId)
      failedPollAuxiliaryDenialsRef.current.delete(taskId)
      terminalConfirmableAuxiliaryDenialsRef.current.delete(taskId)
      const timeout = terminalReconciliationTimeoutsRef.current.get(taskId)
      if (timeout !== undefined) window.clearTimeout(timeout)
      terminalReconciliationTimeoutsRef.current.delete(taskId)
      const reconciliationGeneration =
        (terminalReconciliationGenerationsRef.current.get(taskId) ?? 0) + 1
      terminalReconciliationGenerationsRef.current.set(taskId, reconciliationGeneration)
      void reconcileTerminalTask(taskId, pin.observedAt, reconciliationGeneration)
    }
  }, [
    auxiliaryTaskReadGuard,
    baseTasks,
    permissionDenied,
    reconcileTerminalTask,
    taskListGeneration,
    taskProgressStore,
    terminalTaskPins,
  ])

  const handleUploadFiles = useCallback(
    async (files: File[]) => {
      if (!canWrite || !files.length || uploadPendingRef.current) return
      const uploadableFiles: File[] = []
      const localExclusions: Array<{
        filename: string
        reasonKey: UploadExclusionReasonKey
      }> = []
      for (const file of files) {
        const issue = documentUploadIssue(file)
        if (issue) localExclusions.push({ filename: file.name, reasonKey: issue })
        else uploadableFiles.push(file)
      }
      const formatExclusionDetails = (
        exclusions: Array<{ filename: string; reasonKey: UploadExclusionReasonKey }>,
      ) => {
        const detailItems = exclusions
          .slice(0, 3)
          .map(
            ({ filename, reasonKey }) =>
              `${filename} (${t(($) => $[`newKnowledge.documentUploadExclusion.${reasonKey}`])})`,
          )
        if (exclusions.length > detailItems.length)
          detailItems.push(
            t(($) => $['newKnowledge.documentUploadExclusion.more'], {
              count: exclusions.length - detailItems.length,
            }),
          )
        return detailItems.join('; ')
      }
      if (!uploadableFiles.length) {
        toast.error(
          t(($) => $['newKnowledge.documentUploadRejected'], {
            details: formatExclusionDetails(localExclusions),
          }),
        )
        return
      }
      let writePermissionDenied = false
      uploadPendingRef.current = true
      setUploading(true)
      try {
        let acceptedCount = 0
        const exclusions = [...localExclusions]
        if (uploadableFiles.length === 1) {
          await uploadDocument({
            body: { file: uploadableFiles[0]! },
            params: { id: knowledgeSpaceId },
          })
          acceptedCount = 1
        } else {
          const result = await bulkUploadDocuments({
            body: { files: uploadableFiles },
            params: { id: knowledgeSpaceId },
          })
          acceptedCount = result.accepted
          for (const item of result.items) {
            if (!('reason' in item)) continue
            const reasonKey = uploadExclusionReasonKey[item.reason]
            exclusions.push({ filename: item.filename, reasonKey })
          }
        }
        const exclusionDetails = formatExclusionDetails(exclusions)
        if (!acceptedCount) {
          toast.error(
            t(($) => $['newKnowledge.documentUploadRejected'], {
              details: exclusionDetails,
            }),
          )
          return
        }
        if (exclusions.length)
          toast.warning(
            t(($) => $['newKnowledge.documentUploadPartial'], {
              accepted: acceptedCount,
              details: exclusionDetails,
              excluded: exclusions.length,
            }),
          )
        else toast.success(t(($) => $['newKnowledge.documentUploadStarted']))
        refreshDocumentsAndTasks()
      } catch (error) {
        if (responseStatus(error) === 403) {
          writePermissionDenied = true
          handleWritePermissionDenied()
        } else toast.error(t(($) => $['newKnowledge.documentUploadFailed']))
      } finally {
        if (!writePermissionDenied) {
          writePermissionFocusRecoveryRequestedRef.current = false
          writePermissionFocusOriginRef.current = null
        }
        uploadPendingRef.current = false
        setUploading(false)
      }
    },
    [
      bulkUploadDocuments,
      canWrite,
      handleWritePermissionDenied,
      knowledgeSpaceId,
      refreshDocumentsAndTasks,
      t,
      uploadDocument,
    ],
  )

  const handleReindexDocuments = useCallback(async () => {
    if (
      !canWrite ||
      selectionDisabled ||
      !validSelectedDocumentIds.size ||
      reindexPendingRef.current
    )
      return
    reindexPendingRef.current = true
    setReindexing(true)
    try {
      const selectedIds = [...validSelectedDocumentIds].sort()
      const result = await reindexDocuments({
        body: { documentIds: selectedIds },
        params: { id: knowledgeSpaceId },
      })
      const missingIds = result.items
        .filter((item) => item.status === 'not_found')
        .map((item) => item.documentId)
      const queuedCount = result.items.length - missingIds.length
      if (!queuedCount) {
        setSelectedDocumentIds(new Set())
        toast.error(
          t(($) => $['newKnowledge.documentsReindexPartial'], {
            missing: missingIds.length,
            queued: 0,
          }),
        )
        refreshDocumentsAndTasks()
        return
      }
      setSelectedDocumentIds(new Set(missingIds))
      if (missingIds.length)
        toast.warning(
          t(($) => $['newKnowledge.documentsReindexPartial'], {
            missing: missingIds.length,
            queued: queuedCount,
          }),
        )
      else toast.success(t(($) => $['newKnowledge.documentsReindexStarted']))
      refreshDocumentsAndTasks()
    } catch (error) {
      if (responseStatus(error) === 403) handleWritePermissionDenied()
      else toast.error(t(($) => $['newKnowledge.documentsReindexFailed']))
    } finally {
      reindexPendingRef.current = false
      setReindexing(false)
    }
  }, [
    canWrite,
    handleWritePermissionDenied,
    knowledgeSpaceId,
    refreshDocumentsAndTasks,
    reindexDocuments,
    selectionDisabled,
    t,
    validSelectedDocumentIds,
  ])

  const handleTaskEvent = useCallback(
    (taskId: string, taskVersion: string, event: ProcessingTaskEvent) => {
      const eventVersion = event.event === 'progress' ? event.data.updatedAt : taskVersion
      const terminalSnapshot = !ACTIVE_TASK_STATES.has(event.data.state)
      const currentVersion = currentTaskVersionRef.current.get(taskId)
      if (currentVersion && taskVersionIsAfter(currentVersion, eventVersion)) {
        if (terminalSnapshot) pendingTerminalProgressRef.current.delete(taskId)
        return false
      }

      if (event.event === 'progress' && ACTIVE_TASK_STATES.has(event.data.state)) {
        if (trustedActiveOverrideVersionsRef.current.get(taskId)?.updatedAt === eventVersion)
          streamActiveOverrideVersionsRef.current.delete(taskId)
        else streamActiveOverrideVersionsRef.current.set(taskId, eventVersion)
      } else streamActiveOverrideVersionsRef.current.delete(taskId)

      if (event.event === 'progress' && terminalSnapshot) {
        currentTaskVersionRef.current.set(taskId, eventVersion)
        taskProgressStore.set(taskId, event.data)
        pendingTerminalProgressRef.current.set(taskId, event)
        return true
      }

      const pendingTerminalProgress =
        event.event === 'terminal' ? pendingTerminalProgressRef.current.get(taskId) : undefined
      if (event.event === 'terminal') pendingTerminalProgressRef.current.delete(taskId)

      if (event.event === 'progress') taskProgressStore.set(taskId, event.data)
      else taskProgressStore.delete(taskId)

      const currentTaskState = currentTaskStateRef.current.get(taskId)
      currentTaskVersionRef.current.set(taskId, eventVersion)
      if (event.event === 'progress' && currentTaskState === event.data.state) return true
      currentTaskStateRef.current.set(taskId, event.data.state)

      setTaskOverrides((current) => {
        const previous = current[taskId]
        if (
          event.event === 'progress' &&
          previous?.updatedAt &&
          taskVersionIsAfter(previous.updatedAt, event.data.updatedAt)
        )
          return current
        return {
          ...current,
          [taskId]:
            event.event === 'progress'
              ? {
                  errorCode: undefined,
                  errorMessage: undefined,
                  progressPercent: event.data.progressPercent,
                  stage: event.data.stage,
                  state: event.data.state,
                  updatedAt: event.data.updatedAt,
                }
              : {
                  errorCode: event.data.errorCode,
                  errorMessage: undefined,
                  ...(pendingTerminalProgress
                    ? {
                        progressPercent: pendingTerminalProgress.data.progressPercent,
                        stage: pendingTerminalProgress.data.stage,
                      }
                    : {}),
                  state: event.data.state,
                  updatedAt: eventVersion,
                },
        }
      })
      if (event.event === 'terminal') {
        const pollGeneration = failedTaskPollGenerationsRef.current.get(taskId) ?? 0
        failedTaskPollGenerationsRef.current.set(taskId, pollGeneration + 1)
        const timeout = terminalReconciliationTimeoutsRef.current.get(taskId)
        if (timeout !== undefined) window.clearTimeout(timeout)
        terminalReconciliationTimeoutsRef.current.delete(taskId)
        const reconciliationGeneration =
          (terminalReconciliationGenerationsRef.current.get(taskId) ?? 0) + 1
        terminalReconciliationGenerationsRef.current.set(taskId, reconciliationGeneration)
        setTerminalTaskPins((current) => ({
          ...current,
          [taskId]: {
            observedAt: eventVersion,
            taskListGeneration: taskListGenerationRef.current,
          },
        }))
        if (event.data.state === 'failed')
          toast.error(t(($) => $['newKnowledge.taskFailedNotification']))
        refreshDocuments()
        void reconcileTerminalTask(taskId, eventVersion, reconciliationGeneration)
      }
      return true
    },
    [reconcileTerminalTask, refreshDocuments, t, taskProgressStore],
  )

  const handleTaskUpdated = useCallback(
    (task: DocumentProcessingTask) => {
      const currentVersion = currentTaskVersionRef.current.get(task.id)
      if (currentVersion && taskVersionIsAfter(currentVersion, task.updatedAt)) return
      streamActiveOverrideVersionsRef.current.delete(task.id)
      auxiliaryTaskReadGuard.clearTask(task.id)
      failedPollAuxiliaryDenialsRef.current.delete(task.id)
      terminalConfirmableAuxiliaryDenialsRef.current.delete(task.id)
      if (taskIsActive(task))
        trustedActiveOverrideVersionsRef.current.set(task.id, {
          taskListGeneration: taskListGenerationRef.current,
          updatedAt: task.updatedAt,
        })
      else trustedActiveOverrideVersionsRef.current.delete(task.id)
      trustedOverrideListGenerationsRef.current.delete(task.id)
      taskProgressStore.delete(task.id)
      currentTaskStateRef.current.set(task.id, task.state)
      currentTaskVersionRef.current.set(task.id, task.updatedAt)
      // oxlint-disable-next-line eslint-react/set-state-in-effect -- A committed active list lifecycle retires the denied failed snapshot.
      setTaskOverrides((current) => ({ ...current, [task.id]: normalizedTaskSnapshot(task) }))
      if (taskIsActive(task)) {
        blockedFailedTaskPollVersionsRef.current.delete(task.id)
        taskEventCursorsRef.current.delete(task.id)
        terminalReconciliationControllersRef.current.get(task.id)?.abort()
        terminalReconciliationControllersRef.current.delete(task.id)
        const timeout = terminalReconciliationTimeoutsRef.current.get(task.id)
        if (timeout !== undefined) window.clearTimeout(timeout)
        terminalReconciliationTimeoutsRef.current.delete(task.id)
        const generation = terminalReconciliationGenerationsRef.current.get(task.id) ?? 0
        terminalReconciliationGenerationsRef.current.set(task.id, generation + 1)
        const pollGeneration = failedTaskPollGenerationsRef.current.get(task.id) ?? 0
        failedTaskPollGenerationsRef.current.set(task.id, pollGeneration + 1)
        pendingTerminalProgressRef.current.delete(task.id)
        // oxlint-disable-next-line eslint-react/set-state-in-effect -- The authoritative active lifecycle supersedes the terminal pin.
        setTerminalTaskPins((current) => {
          const next = { ...current }
          delete next[task.id]
          return next
        })
      }
    },
    [auxiliaryTaskReadGuard, taskProgressStore],
  )

  useEffect(() => {
    if (permissionDenied) return
    for (const task of baseTasks) {
      if (!taskIsActive(task)) continue
      const denial = failedPollAuxiliaryDenialsRef.current.get(task.id)
      if (!denial || taskListGeneration <= denial.taskListGeneration) continue
      if (taskVersionIsAfter(denial.taskVersion, task.updatedAt)) continue
      failedPollAuxiliaryDenialsRef.current.delete(task.id)
      handleTaskUpdated(task)
    }
  }, [baseTasks, handleTaskUpdated, permissionDenied, taskListGeneration])

  useEffect(() => {
    for (const task of activeTasks) {
      const hadBlockedPoll = blockedFailedTaskPollVersionsRef.current.delete(task.id)
      if (!hadBlockedPoll) continue
      const generation = failedTaskPollGenerationsRef.current.get(task.id) ?? 0
      failedTaskPollGenerationsRef.current.set(task.id, generation + 1)
    }
  }, [activeTasks])

  useEffect(() => {
    if (permissionDenied || !orderedFailedTasksRef.current.length) return
    let canceled = false
    let timeout: number | undefined
    const cancelRequests = new Set<() => void>()
    const pollNextBatch = async () => {
      const failedTasks = orderedFailedTasksRef.current
      const pollableTasks = failedTasks.filter(
        (task) =>
          blockedFailedTaskPollVersionsRef.current.get(task.id) !== task.updatedAt &&
          !auxiliaryTaskReadGuard.isBlocked(task.id, task.updatedAt),
      )
      if (pollableTasks.length) {
        const pollCount = Math.min(MAX_TASK_EVENT_STREAMS, pollableTasks.length)
        const offset = failedTaskPollOffsetRef.current % pollableTasks.length
        const tasksToPoll = Array.from(
          { length: pollCount },
          (_, index) => pollableTasks[(offset + index) % pollableTasks.length]!,
        )
        failedTaskPollOffsetRef.current += MAX_TASK_EVENT_STREAMS
        await Promise.allSettled(
          tasksToPoll.map(async (task) => {
            const requestGeneration = (failedTaskPollGenerationsRef.current.get(task.id) ?? 0) + 1
            failedTaskPollGenerationsRef.current.set(task.id, requestGeneration)
            const requestController = new AbortController()
            let requestTimeout: number | undefined
            let rejectDeadline: ((reason?: unknown) => void) | undefined
            const cancelRequest = () => {
              requestController.abort()
              rejectDeadline?.(new DOMException('Task snapshot request aborted', 'AbortError'))
            }
            try {
              const request =
                consoleClient.knowledgeFs.getKnowledgeSpacesByIdDocumentsByDocumentIdProcessingTasksByTaskId(
                  {
                    params: {
                      documentId: task.documentId,
                      id: knowledgeSpaceId,
                      taskId: task.id,
                    },
                  },
                  { signal: requestController.signal },
                )
              const deadline = new Promise<never>((_resolve, reject) => {
                rejectDeadline = reject
                requestTimeout = window.setTimeout(() => {
                  requestController.abort()
                  reject(new DOMException('Task snapshot request timed out', 'TimeoutError'))
                }, FAILED_TASK_POLL_REQUEST_TIMEOUT)
              })
              cancelRequests.add(cancelRequest)
              const snapshot = await Promise.race([request, deadline])
              if (
                canceled ||
                failedTaskPollGenerationsRef.current.get(task.id) !== requestGeneration
              )
                return
              const currentVersion = currentTaskVersionRef.current.get(task.id)
              if (currentVersion && taskVersionIsAfter(currentVersion, snapshot.updatedAt)) return
              handleTaskUpdated(snapshot)
            } catch (error) {
              if (
                canceled ||
                failedTaskPollGenerationsRef.current.get(task.id) !== requestGeneration
              )
                return
              if (responseStatus(error) === 403) {
                const currentTaskVersion = currentTaskVersionRef.current.get(task.id)
                const deniedVersion =
                  currentTaskVersion && taskVersionIsAfter(currentTaskVersion, task.updatedAt)
                    ? currentTaskVersion
                    : task.updatedAt
                failedPollAuxiliaryDenialsRef.current.set(task.id, {
                  taskListGeneration: taskListGenerationRef.current,
                  taskVersion: deniedVersion,
                })
                denyAuxiliaryTaskRead(task.id, deniedVersion)
                return
              }
              if (!taskSnapshotErrorIsTransient(error))
                blockedFailedTaskPollVersionsRef.current.set(task.id, task.updatedAt)
            } finally {
              if (requestTimeout !== undefined) window.clearTimeout(requestTimeout)
              cancelRequests.delete(cancelRequest)
            }
          }),
        )
      }
      if (!canceled) timeout = window.setTimeout(() => void pollNextBatch(), 5000)
    }
    timeout = window.setTimeout(() => void pollNextBatch(), 5000)
    return () => {
      canceled = true
      for (const cancelRequest of cancelRequests) cancelRequest()
      cancelRequests.clear()
      if (timeout !== undefined) window.clearTimeout(timeout)
    }
  }, [
    auxiliaryTaskReadGuard,
    denyAuxiliaryTaskRead,
    failedTaskPollSignature,
    handleTaskUpdated,
    knowledgeSpaceId,
    permissionDenied,
  ])

  const toggleDocument = useCallback(
    (documentId: string) => {
      if (!canWrite || selectionDisabled) return
      setSelectedDocumentIds((current) => {
        const next = new Set(current)
        if (next.has(documentId)) next.delete(documentId)
        else next.add(documentId)
        return next
      })
    },
    [canWrite, selectionDisabled],
  )

  const toggleAllFiltered = () => {
    if (!canWrite || selectionDisabled) return
    setSelectedDocumentIds((current) => {
      const next = new Set(current)
      if (allFilteredSelected)
        selectableFilteredDocuments.forEach((document) => next.delete(document.id))
      else selectableFilteredDocuments.forEach((document) => next.add(document.id))
      return next
    })
  }

  const retryDependencyQueries = () => {
    if (taskQueryBlockingError || sourceQueryBlockingError)
      setBlockingDependencyRetries((current) => ({
        sources: current.sources || sourceQueryBlockingError,
        tasks: current.tasks || taskQueryBlockingError,
      }))
    if (tasksQuery.isFetchNextPageError) void tasksQuery.fetchNextPage()
    else if (tasksQuery.error || taskQueryBlockingError) void tasksQuery.refetch()
    if (sourcesQuery.isFetchNextPageError) void sourcesQuery.fetchNextPage()
    else if (sourcesQuery.error || sourceQueryBlockingError) void sourcesQuery.refetch()
  }

  const loadMoreResults = () => {
    const requests: Promise<unknown>[] = []
    if (hasNextDocumentPage && !isFetchingNextDocumentPage) requests.push(fetchNextDocumentPage())
    if (hasNextTaskPage && !isFetchingNextTaskPage) requests.push(fetchNextTaskPage())
    if (hasRelevantNextSourcePage && !isFetchingNextSourcePage) requests.push(fetchNextSourcePage())
    void Promise.allSettled(requests)
  }

  const handleTaskEventCursor = useCallback((taskId: string, eventId?: string) => {
    if (eventId) taskEventCursorsRef.current.set(taskId, eventId)
    else taskEventCursorsRef.current.delete(taskId)
  }, [])

  const handleTaskStreamPermissionDenied = useCallback(
    (taskId: string, taskVersion: string) => {
      terminalConfirmableAuxiliaryDenialsRef.current.set(taskId, {
        taskListGeneration: taskListGenerationRef.current,
        taskVersion,
      })
      denyAuxiliaryTaskRead(taskId, taskVersion)
    },
    [denyAuxiliaryTaskRead],
  )

  return (
    <>
      {streamedActiveTasks.map((task) => {
        const observerVersion = taskObserverVersion(task)
        return (
          <TaskEventObserver
            key={`${task.id}:${taskObserverGenerations[task.id] ?? 0}`}
            documentId={task.documentId}
            knowledgeSpaceId={knowledgeSpaceId}
            lastEventId={taskEventCursorsRef.current.get(task.id)}
            onEvent={handleTaskEvent}
            onLastEventIdChange={handleTaskEventCursor}
            onPermissionDenied={handleTaskStreamPermissionDenied}
            taskId={task.id}
            taskVersion={observerVersion}
          />
        )
      })}
      {canWrite && (
        <input
          ref={uploadInputRef}
          multiple
          hidden
          accept={DOCUMENT_UPLOAD_ACCEPT}
          aria-label={t(($) => $['newKnowledge.uploadDocuments'])}
          tabIndex={-1}
          type="file"
          onChange={(event) => {
            const files = [...(event.currentTarget.files ?? [])]
            event.currentTarget.value = ''
            void handleUploadFiles(files)
          }}
        />
      )}
      <section
        ref={documentsSectionRef}
        className={cn(
          'flex min-h-full flex-col px-4 pt-6 sm:px-8 sm:pt-7',
          bulkActionsVisible ? 'pb-[calc(7rem+env(safe-area-inset-bottom,0px))]' : 'pb-6 sm:pb-7',
        )}
        onBlurCapture={(event) => {
          if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {
            documentSurfaceHadFocusRef.current = false
            if (event.relatedTarget && event.relatedTarget !== uploadInputRef.current) {
              writePermissionFocusRecoveryRequestedRef.current = false
              writePermissionFocusOriginRef.current = null
            }
          }
        }}
        onFocusCapture={(event) => {
          if (
            writePermissionFocusRecoveryRequestedRef.current &&
            event.target !== writePermissionFocusOriginRef.current
          ) {
            writePermissionFocusRecoveryRequestedRef.current = false
            writePermissionFocusOriginRef.current = null
          }
          documentSurfaceHadFocusRef.current = true
        }}
      >
        <header>
          <h2
            ref={documentsTitleRef}
            id="new-knowledge-documents-title"
            className="title-xl-semi-bold text-text-primary"
            tabIndex={-1}
          >
            {t(($) => $['newKnowledge.documents'])}
          </h2>
          <p className="mt-1 system-xs-regular text-text-tertiary">
            {t(($) => $['newKnowledge.documentsDescription'])}
          </p>
          {permissionPending && (
            <p
              id="documents-permission-pending"
              className="mt-2 system-xs-regular text-text-tertiary"
              role="status"
            >
              {t(($) => $['newKnowledge.permission'])}
              {' · '}
              {tCommon(($) => $.loading)}
            </p>
          )}
          {!permissionPending && !permissionQueryError && (!canEdit || writePermissionRevoked) && (
            <p
              id="documents-readonly-reason"
              className="mt-2 inline-flex items-center gap-1.5 system-xs-regular text-text-warning"
              role="status"
            >
              <span aria-hidden className="i-ri-lock-line size-3.5" />
              {t(($) => $['newKnowledge.documentPermissionRestricted'])}
            </p>
          )}
        </header>
        {permissionQueryError && (
          <div
            className="mt-4 flex items-center justify-between gap-3 rounded-lg border border-divider-regular bg-background-section px-3 py-2"
            role="alert"
          >
            <span id="documents-permission-error" className="system-xs-regular text-text-tertiary">
              {t(($) => $['newKnowledge.permissionLoadFailed'])}
            </span>
            <Button
              ref={permissionRetryButtonRef}
              aria-label={`${tCommon(($) => $['operation.retry'])} · ${t(($) => $['newKnowledge.permissionLoadFailed'])}`}
              aria-busy={workspacePermissionKeysFetching}
              loading={workspacePermissionKeysFetching}
              size="small"
              onBlur={(event) => {
                if (event.relatedTarget) mainRetryFocusRequestedRef.current = false
              }}
              onClick={() => {
                mainRetryFocusRequestedRef.current = true
                void refreshWorkspacePermissions(true)
              }}
            >
              {tCommon(($) => $['operation.retry'])}
            </Button>
          </div>
        )}
        {documentsQuery.error &&
          documentsQuery.data &&
          !permissionDenied &&
          !documentsQuery.isFetchNextPageError && (
            <div
              className="mt-4 flex items-center justify-between gap-3 rounded-lg border border-divider-regular bg-background-section px-3 py-2"
              role="alert"
            >
              <span className="system-xs-regular text-text-tertiary">
                {t(($) =>
                  responseStatus(documentsQuery.error) === 403
                    ? $['newKnowledge.documentsPermissionDescription']
                    : $['newKnowledge.documentsErrorDescription'],
                )}
              </span>
              {responseStatus(documentsQuery.error) !== 403 && (
                <Button
                  ref={documentsRetryButtonRef}
                  aria-label={`${tCommon(($) => $['operation.retry'])} · ${t(($) => $['newKnowledge.documentsErrorDescription'])}`}
                  aria-busy={documentsQuery.isRefetching}
                  loading={documentsQuery.isRefetching}
                  size="small"
                  onBlur={(event) => {
                    if (event.relatedTarget) mainRetryFocusRequestedRef.current = false
                  }}
                  onClick={() => {
                    mainRetryFocusRequestedRef.current = true
                    void refetchDocumentsQuery()
                  }}
                >
                  {tCommon(($) => $['operation.retry'])}
                </Button>
              )}
            </div>
          )}
        {!permissionDenied && !dependencyQueryBlockingError && dependencyQueryWarning && (
          <div
            className="mt-4 flex items-center justify-between gap-3 rounded-lg border border-divider-regular bg-background-section px-3 py-2"
            role="alert"
          >
            <span className="system-xs-regular text-text-tertiary">
              {sourcesQuery.error || sourcesQuery.isFetchNextPageError
                ? t(($) => $['newKnowledge.sourcesErrorDescription'])
                : t(($) => $['newKnowledge.tasksErrorDescription'])}
            </span>
            <Button
              ref={dependencyRetryButtonRef}
              aria-label={`${tCommon(($) => $['operation.retry'])} · ${
                sourcesQuery.error || sourcesQuery.isFetchNextPageError
                  ? t(($) => $['newKnowledge.sourcesErrorDescription'])
                  : t(($) => $['newKnowledge.tasksErrorDescription'])
              }`}
              aria-busy={dependencyRetryFetching}
              loading={dependencyRetryFetching}
              size="small"
              onBlur={(event) => {
                if (event.relatedTarget) mainRetryFocusRequestedRef.current = false
              }}
              onClick={() => {
                mainRetryFocusRequestedRef.current = true
                retryDependencyQueries()
              }}
            >
              {tCommon(($) => $['operation.retry'])}
            </Button>
          </div>
        )}
        {documentsQuery.isPending && !permissionDenied ? (
          <div className="flex min-h-64 flex-1 items-center justify-center">
            <Loading />
          </div>
        ) : permissionDenied || (documentsQuery.error && !documentsQuery.data) ? (
          <div
            ref={documentPermissionAlertRef}
            className="flex min-h-64 flex-1 flex-col items-center justify-center px-6 text-center"
            role="alert"
            tabIndex={permissionDenied ? -1 : undefined}
          >
            <span aria-hidden className="i-ri-error-warning-line size-7 text-text-tertiary" />
            <h2 className="mt-3 title-xl-semi-bold text-text-primary">
              {t(($) =>
                permissionDenied
                  ? $['newKnowledge.documentsPermissionTitle']
                  : $['newKnowledge.documentsErrorTitle'],
              )}
            </h2>
            <p className="mt-2 max-w-md body-sm-regular text-text-tertiary">
              {t(($) =>
                permissionDenied
                  ? $['newKnowledge.documentsPermissionDescription']
                  : $['newKnowledge.documentsErrorDescription'],
              )}
            </p>
            {(!permissionDenied ||
              (auxiliaryReadPermissionDenied && !documentPermissionDenied)) && (
              <Button
                ref={documentsRetryButtonRef}
                aria-label={`${tCommon(($) => $['operation.retry'])} · ${documentsRecoveryDescription}`}
                aria-busy={documentsQuery.isFetching}
                className="mt-4"
                loading={documentsQuery.isFetching}
                onBlur={(event) => {
                  if (event.relatedTarget) mainRetryFocusRequestedRef.current = false
                }}
                onClick={() => {
                  mainRetryFocusRequestedRef.current = true
                  if (auxiliaryReadPermissionDenied) retryAuxiliaryTaskRead()
                  else void refetchDocumentsQuery()
                }}
              >
                {tCommon(($) => $['operation.retry'])}
              </Button>
            )}
          </div>
        ) : dependencyQueryBlockingError ? (
          <div
            className="flex min-h-64 flex-1 flex-col items-center justify-center px-6 text-center"
            role="alert"
          >
            <span aria-hidden className="i-ri-error-warning-line size-7 text-text-tertiary" />
            <p className="mt-3 max-w-md body-sm-regular text-text-tertiary">
              {taskQueryBlockingError
                ? t(($) => $['newKnowledge.tasksErrorDescription'])
                : t(($) => $['newKnowledge.sourcesErrorDescription'])}
            </p>
            <Button
              ref={dependencyRetryButtonRef}
              aria-label={`${tCommon(($) => $['operation.retry'])} · ${
                taskQueryBlockingError
                  ? t(($) => $['newKnowledge.tasksErrorDescription'])
                  : t(($) => $['newKnowledge.sourcesErrorDescription'])
              }`}
              aria-busy={blockingDependencyRetryFetching}
              className="mt-4"
              loading={blockingDependencyRetryFetching}
              onBlur={(event) => {
                if (event.relatedTarget) mainRetryFocusRequestedRef.current = false
              }}
              onClick={() => {
                mainRetryFocusRequestedRef.current = true
                retryDependencyQueries()
              }}
            >
              {tCommon(($) => $['operation.retry'])}
            </Button>
          </div>
        ) : !documents.length ? (
          <DocumentsEmpty
            activeTaskCount={activeTasks.length}
            attentionTaskBadge={attentionTaskBadge}
            canEdit={canWrite}
            hasTaskError={hasTaskError}
            onAddDocument={() => {
              writePermissionFocusRecoveryRequestedRef.current = true
              writePermissionFocusOriginRef.current = document.activeElement as HTMLElement | null
              uploadInputRef.current?.click()
            }}
            onDropFiles={(files) => void handleUploadFiles(files)}
            onOpenTasks={() => setTasksOpen(true)}
            readOnlyReasonId={documentWriteRestrictionReasonId}
            tasksButtonLabel={tasksButtonLabel}
            tasksLiveStatus={tasksLiveStatus}
            uploading={uploading}
          />
        ) : (
          <DocumentsList
            activeTaskCount={activeTasks.length}
            allSelected={allFilteredSelected}
            attentionTaskBadge={attentionTaskBadge}
            canEdit={canWrite}
            completingResults={completingFilteredResults}
            documents={filteredDocuments}
            filter={filter}
            getDocumentHref={(documentId) =>
              newKnowledgeDocumentDetailPath(knowledgeSpaceId, documentId)
            }
            hasNextPage={Boolean(
              hasNextDocumentPage || hasNextTaskPage || hasRelevantNextSourcePage,
            )}
            hasSelectableDocuments={Boolean(selectableFilteredDocuments.length)}
            hasTaskError={hasTaskError}
            isFetchNextPageError={documentsQuery.isFetchNextPageError}
            isFetchingNextDocumentPage={isFetchingNextDocumentPage}
            isFetchingNextPage={isFetchingNextResultsPage}
            onAddDocument={() => {
              writePermissionFocusRecoveryRequestedRef.current = true
              writePermissionFocusOriginRef.current = document.activeElement as HTMLElement | null
              uploadInputRef.current?.click()
            }}
            onFilterChange={setFilter}
            onLoadMore={loadMoreResults}
            onOpenTasks={() => setTasksOpen(true)}
            onSearchChange={setSearch}
            onSelectAll={toggleAllFiltered}
            onSelectDocument={toggleDocument}
            readOnlyReasonId={documentWriteRestrictionReasonId}
            resultsIncomplete={filteredResultsIncomplete}
            search={search}
            selectionDisabled={selectionDisabled}
            selectedDocumentIds={validSelectedDocumentIds}
            someSelected={someFilteredSelected}
            sourcesPending={sourceResultsIncomplete}
            sourceNames={sourceNames}
            statusPending={dependencyResultsIncomplete}
            statuses={documentStatuses}
            tasksPending={taskResultsIncomplete}
            tasksButtonLabel={tasksButtonLabel}
            tasksLiveStatus={tasksLiveStatus}
            uploading={uploading}
          />
        )}
      </section>
      {bulkActionsVisible && (
        <DocumentBulkActions
          disabled={selectionDisabled}
          disabledReason={reindexUnavailableReason}
          onClear={() => setSelectedDocumentIds(new Set())}
          onBlurCapture={(event) => {
            if (!event.currentTarget.contains(event.relatedTarget as Node | null))
              bulkActionsHadFocusRef.current = false
          }}
          onFocusCapture={() => {
            bulkActionsHadFocusRef.current = true
          }}
          onReindex={() => void handleReindexDocuments()}
          reindexing={reindexing}
          selectedCount={validSelectedDocumentIds.size}
        />
      )}
      <ProcessingTasksDrawer
        actionResultsValid={!permissionDenied}
        canEdit={canWrite}
        documentQueryError={Boolean(documentsQuery.error || documentsQuery.isFetchNextPageError)}
        documentQueryFetching={documentsQuery.isFetching}
        documents={documents}
        documentsPending={Boolean(hasNextDocumentPage || documentsQuery.isFetchingNextPage)}
        hasNextDocumentPage={Boolean(hasNextDocumentPage)}
        hasNextTaskPage={Boolean(hasNextTaskPage)}
        hasUnresolvedTaskDocuments={unresolvedTaskDocumentIds.size > 0}
        isFetchingNextDocumentPage={isFetchingNextDocumentPage}
        isFetchingNextTaskPage={isFetchingNextTaskPage}
        knowledgeSpaceId={knowledgeSpaceId}
        onLoadMoreDocuments={() => void fetchNextDocumentPage()}
        onLoadMoreTasks={() => void fetchNextTaskPage()}
        onOpenChange={setTasksOpen}
        onRefreshDocumentsAndTasks={refreshDocumentsAndTasks}
        onRetryPermissionQuery={() => void refreshWorkspacePermissions(true)}
        onRetryDocumentQuery={() => {
          if (documentsQuery.isFetchNextPageError) void documentsQuery.fetchNextPage()
          else void refetchDocumentsQuery()
        }}
        onRetryTaskQuery={() => {
          if (tasksQuery.isFetchNextPageError) void tasksQuery.fetchNextPage()
          else void tasksQuery.refetch()
        }}
        onTaskUpdated={handleTaskUpdated}
        onWritePermissionDenied={handleWritePermissionDenied}
        open={tasksOpen && !permissionDenied}
        permissionQueryError={permissionQueryError}
        permissionQueryFetching={workspacePermissionKeysFetching}
        permissionQueryPending={permissionPending}
        readOnlyReason={
          writePermissionRevoked || (!permissionPending && !permissionQueryError && !canEdit)
            ? t(($) => $['newKnowledge.documentPermissionRestricted'])
            : undefined
        }
        taskQueryPending={tasksQuery.isPending}
        taskQueryError={Boolean(tasksQuery.error || tasksQuery.isFetchNextPageError)}
        taskQueryFetching={tasksQuery.isFetching}
        taskProgressStore={taskProgressStore}
        tasks={tasks}
      />
    </>
  )
}
