// SPDX-FileCopyrightText: 2025 Weibo, Inc.
//
// SPDX-License-Identifier: Apache-2.0

'use client'

import { useState, useMemo, useEffect, useRef, useCallback, Suspense } from 'react'
import {
  ArrowLeft,
  Upload,
  FileText,
  Search,
  ChevronUp,
  ChevronDown,
  BookOpen,
  Database,
  Trash2,
  Target,
  FileUp,
  RefreshCw,
  Info,
  CheckSquare,
  Square,
  AlertTriangle,
  FolderPlus,
} from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Spinner } from '@/components/ui/spinner'
import { Checkbox } from '@/components/ui/checkbox'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { DocumentDetailDialog } from './DocumentDetailDialog'
import { DocumentUpload, type TableDocument } from './DocumentUpload'
import { DeleteDocumentDialog } from './DeleteDocumentDialog'
import { EditDocumentDialog } from './EditDocumentDialog'
import { RetrievalTestDialog } from './RetrievalTestDialog'
import { useDocuments } from '../hooks/useDocuments'
import { useFolders } from '../hooks/useFolders'
import { FolderTree, type SortField, type SortOrder } from './FolderTree'
import { CreateFolderDialog } from './CreateFolderDialog'
import { DeleteFolderDialog } from './DeleteFolderDialog'
import { MoveDocumentDialog } from './MoveDocumentDialog'
import { useColumnResize } from '../hooks/useColumnResize'
import { refreshKnowledgeBaseSummary } from '@/apis/knowledge'
import { toast } from '@/hooks/use-toast'
import type {
  KnowledgeBase,
  KnowledgeDocument,
  KnowledgeFolder,
  SplitterConfig,
  KbGroupInfo,
} from '@/types/knowledge'
import { useTranslation } from '@/hooks/useTranslation'
import { useUser } from '@/features/common/UserContext'
import { useSearchParams, useRouter, usePathname } from 'next/navigation'

/**
 * Inner component that uses useSearchParams (must be inside Suspense boundary).
 * Reads the ?doc= URL parameter and auto-opens the matching document.
 */
function DocAutoOpener({
  documents,
  loading,
  onOpen,
}: {
  documents: KnowledgeDocument[]
  loading: boolean
  onOpen: (doc: KnowledgeDocument) => void
}) {
  const searchParams = useSearchParams()
  const router = useRouter()
  const pathname = usePathname()
  const [done, setDone] = useState(false)

  useEffect(() => {
    if (done || loading || documents.length === 0) return
    const docParam = searchParams.get('doc')
    if (!docParam) {
      setDone(true)
      return
    }
    // Find document by name (exact match)
    const targetDoc = documents.find(doc => doc.name === docParam)
    if (targetDoc) {
      onOpen(targetDoc)
      // Remove the ?doc= param from URL without triggering navigation
      const params = new URLSearchParams(searchParams.toString())
      params.delete('doc')
      const newSearch = params.toString()
      router.replace(pathname + (newSearch ? `?${newSearch}` : ''), { scroll: false })
    }
    setDone(true)
  }, [done, loading, documents, searchParams, onOpen, router, pathname])

  return null
}

// Re-export KbGroupInfo from types for backwards compatibility
export type { KbGroupInfo } from '@/types/knowledge'

interface DocumentListProps {
  knowledgeBase: KnowledgeBase
  onBack?: () => void
  canUpload?: boolean
  canManageAllDocuments?: boolean
  /** Compact mode for sidebar display - uses card layout instead of table */
  compact?: boolean
  /** Callback when document selection changes (for notebook mode context injection) */
  onSelectionChange?: (documentIds: number[]) => void
  /** Callback to refresh knowledge base details (used after summary retry) */
  onRefreshKnowledgeBase?: () => void
  /** Optional header actions to display next to the title (e.g., tabs) */
  headerActions?: React.ReactNode
  /** Group info for breadcrumb display */
  groupInfo?: KbGroupInfo
  /** Callback when group name is clicked */
  onGroupClick?: (groupId: string, groupType?: string) => void
  /** Initial document path to auto-open (from virtual URL path segments) */
  initialDocPath?: string
  /** Whether this KB belongs to an organization-level namespace (affects URL format in DocumentDetailDialog) */
  isOrganization?: boolean
}

/** Flatten folder tree into a flat list for select dropdowns */
function flattenFoldersForSelect(
  folders: KnowledgeFolder[],
  depth: number = 0
): Array<{ id: number; name: string; depth: number }> {
  let result: Array<{ id: number; name: string; depth: number }> = []
  for (const folder of folders) {
    result.push({ id: folder.id, name: folder.name, depth })
    result = result.concat(flattenFoldersForSelect(folder.children, depth + 1))
  }
  return result
}

export function DocumentList({
  knowledgeBase,
  onBack,
  canUpload = true,
  canManageAllDocuments = false,
  compact = false,
  onSelectionChange,
  onRefreshKnowledgeBase,
  headerActions,
  groupInfo,
  onGroupClick,
  initialDocPath,
  isOrganization = false,
}: DocumentListProps) {
  const { t } = useTranslation('knowledge')
  const { user } = useUser()
  const { documents, loading, error, create, remove, refresh, batchDelete } = useDocuments({
    knowledgeBaseId: knowledgeBase.id,
  })

  // Folder state
  const { folders, fetchFolders, createFolder, updateFolder, deleteFolder, moveDocument } =
    useFolders({ knowledgeBaseId: knowledgeBase.id })

  const [showCreateFolder, setShowCreateFolder] = useState(false)
  const [createFolderParentId, setCreateFolderParentId] = useState(0)
  const [renamingFolder, setRenamingFolder] = useState<{ id: number; name: string } | null>(null)
  const [deletingFolder, setDeletingFolder] = useState<{ id: number; name: string } | null>(null)

  // Load folders when knowledge base changes
  useEffect(() => {
    if (knowledgeBase.id) {
      fetchFolders()
      setSelectedUploadFolderId(0)
    }
  }, [knowledgeBase.id, fetchFolders])

  // Flatten folder tree for select dropdowns
  const folderOptions = useMemo(() => flattenFoldersForSelect(folders), [folders])

  // Only show error on page for initial load failures (when documents list is empty)
  // Operation errors are shown via toast notifications
  const showLoadError = error && documents.length === 0

  const [showUpload, setShowUpload] = useState(false)
  const [showRetrievalTest, setShowRetrievalTest] = useState(false)
  const [viewingDoc, setViewingDoc] = useState<KnowledgeDocument | null>(null)
  const [editingDoc, setEditingDoc] = useState<KnowledgeDocument | null>(null)
  const [deletingDoc, setDeletingDoc] = useState<KnowledgeDocument | null>(null)
  const [searchQuery, setSearchQuery] = useState('')
  const [sortField, setSortField] = useState<SortField>('createdAt')
  const [sortOrder, setSortOrder] = useState<SortOrder>('desc')
  const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set())
  const [batchLoading, setBatchLoading] = useState(false)
  const [showSearchPopover, setShowSearchPopover] = useState(false)
  // Track if initial selection has been done
  const [initialSelectionDone, setInitialSelectionDone] = useState(false)
  // Track if initialDocPath has been handled
  const [initialDocPathHandled, setInitialDocPathHandled] = useState(false)
  // Track which document is being refreshed
  const [refreshingDocId, setRefreshingDocId] = useState<number | null>(null)
  // Track which document is being reindexed
  const [reindexingDocId, setReindexingDocId] = useState<number | null>(null)
  // Track if summary is being retried
  const [isSummaryRetrying, setIsSummaryRetrying] = useState(false)
  // Track selected upload folder
  const [selectedUploadFolderId, setSelectedUploadFolderId] = useState(0)
  // Track document being moved
  const [movingDoc, setMovingDoc] = useState<KnowledgeDocument | null>(null)
  const [isMovingDoc, setIsMovingDoc] = useState(false)

  // Resizable name column width (normal table mode only)
  const {
    widthOverride: nameColumnWidth,
    isResizing: isColumnResizing,
    handleMouseDown: handleNameResizeMouseDown,
    columnRef: nameColumnRef,
  } = useColumnResize()

  // Track component mounted state to prevent updates after unmount
  const isMountedRef = useRef(true)

  useEffect(() => {
    return () => {
      isMountedRef.current = false
    }
  }, [])

  // Check if summary generation failed
  const isSummaryFailed = knowledgeBase.summary?.status === 'failed'
  const summaryError = knowledgeBase.summary?.error

  // Handle retry summary generation
  const handleRetrySummary = async () => {
    setIsSummaryRetrying(true)
    try {
      await refreshKnowledgeBaseSummary(knowledgeBase.id)
      toast({
        description: t('chatPage.summaryRetrying'),
      })
      // Refresh knowledge base details after a short delay
      if (onRefreshKnowledgeBase) {
        setTimeout(() => {
          if (isMountedRef.current) {
            onRefreshKnowledgeBase()
          }
        }, 2000)
      }
    } catch (err) {
      console.error('Failed to refresh summary:', err)
      toast({
        variant: 'destructive',
        description: t('chatPage.summaryFailed'),
      })
    } finally {
      if (isMountedRef.current) {
        setIsSummaryRetrying(false)
      }
    }
  }

  // Auto-open document from initialDocPath prop (from virtual URL path segments)
  // This runs once when documents are loaded, without modifying the URL
  useEffect(() => {
    if (!initialDocPath || initialDocPathHandled || loading || documents.length === 0) return
    const targetDoc = documents.find(doc => doc.name === initialDocPath)
    if (targetDoc) {
      setViewingDoc(targetDoc)
    }
    setInitialDocPathHandled(true)
  }, [initialDocPath, initialDocPathHandled, loading, documents])

  // Default select all documents when documents load (for notebook mode)
  useEffect(() => {
    if (onSelectionChange && documents.length > 0 && !initialSelectionDone) {
      const allIds = new Set(documents.map(doc => doc.id))
      setSelectedIds(allIds)
      onSelectionChange(Array.from(allIds))
      setInitialSelectionDone(true)
    }
  }, [documents, onSelectionChange, initialSelectionDone])

  // Notify parent when selection changes (after initial selection)
  useEffect(() => {
    if (onSelectionChange && initialSelectionDone) {
      onSelectionChange(Array.from(selectedIds))
    }
  }, [selectedIds, onSelectionChange, initialSelectionDone])

  const filteredDocuments = useMemo(() => {
    if (!searchQuery.trim()) return documents
    const query = searchQuery.toLowerCase()
    return documents.filter(doc => doc.name.toLowerCase().includes(query))
  }, [documents, searchQuery])

  const canManageAnyDocuments = canUpload || canManageAllDocuments

  const canManageDocument = (document: KnowledgeDocument) =>
    canManageAllDocuments || (canUpload && user?.id === document.user_id)

  const canSelectDocument = (document: KnowledgeDocument) =>
    Boolean(onSelectionChange) || (canManageAllDocuments && canManageDocument(document))

  const handleSort = (field: SortField) => {
    if (sortField === field) {
      setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc')
    } else {
      setSortField(field)
      setSortOrder('desc')
    }
  }

  const SortIcon = ({ field }: { field: SortField }) => {
    if (sortField !== field) return null
    return sortOrder === 'asc' ? (
      <ChevronUp className="w-3 h-3 inline ml-1" />
    ) : (
      <ChevronDown className="w-3 h-3 inline ml-1" />
    )
  }

  const handleUploadComplete = async (
    attachments: { attachment: { id: number; filename: string }; file: File }[],
    splitterConfig?: Partial<SplitterConfig>
  ) => {
    // Track newly created document IDs for auto-selection
    const newDocumentIds: number[] = []

    // Create documents sequentially to ensure all are created
    for (const { attachment, file } of attachments) {
      // Use attachment.filename (which may have been renamed) instead of file.name
      const documentName = attachment.filename || file.name
      const extension = documentName.split('.').pop() || ''
      try {
        const created = await create({
          attachment_id: attachment.id,
          name: documentName,
          file_extension: extension,
          file_size: file.size,
          splitter_config: splitterConfig,
          source_type: 'file',
          folder_id: selectedUploadFolderId || 0,
        })
        // Collect newly created document ID
        if (created?.id) {
          newDocumentIds.push(created.id)
        }
      } catch {
        // Continue with next file even if one fails
      }
    }

    // Auto-select newly uploaded documents (for notebook mode context injection)
    if (onSelectionChange && newDocumentIds.length > 0) {
      setSelectedIds(prev => {
        const newSet = new Set(prev)
        newDocumentIds.forEach(id => newSet.add(id))
        return newSet
      })
    }

    setShowUpload(false)
  }

  const handleTableAdd = async (data: TableDocument) => {
    await create({
      name: data.name,
      file_extension: 'table',
      file_size: 0,
      source_type: 'table',
      source_config: data.source_config,
      folder_id: selectedUploadFolderId || 0,
    })
    setShowUpload(false)
  }

  const handleWebAdd = async (url: string, name?: string) => {
    // Import the API function
    const { createWebDocument } = await import('@/apis/knowledge')

    // Call backend API to scrape and create document
    const result = await createWebDocument(url, knowledgeBase.id, name, selectedUploadFolderId || 0)

    if (!result.success) {
      throw new Error(result.error_message || 'Failed to create web document')
    }

    // Refresh document list to show the new document with correct data
    // This ensures the document has the correct source_type from the backend
    await refresh()

    // Auto-select newly created document (for notebook mode context injection)
    if (onSelectionChange && result.document?.id) {
      setSelectedIds(prev => {
        const newSet = new Set(prev)
        newSet.add(result.document!.id)
        return newSet
      })
    }

    setShowUpload(false)
  }

  const handleDelete = async () => {
    if (!deletingDoc) return
    try {
      await remove(deletingDoc.id)
      setDeletingDoc(null)
    } catch {
      // Error handled by hook
    }
  }
  // Batch selection handlers
  const handleSelectDoc = (doc: KnowledgeDocument, selected: boolean) => {
    setSelectedIds(prev => {
      const newSet = new Set(prev)
      if (selected) {
        newSet.add(doc.id)
      } else {
        newSet.delete(doc.id)
      }
      return newSet
    })
  }

  const handleSelectAll = (checked: boolean) => {
    if (checked) {
      setSelectedIds(new Set(filteredDocuments.map(doc => doc.id)))
    } else {
      setSelectedIds(new Set())
    }
  }

  const isAllSelected =
    filteredDocuments.length > 0 && filteredDocuments.every(doc => selectedIds.has(doc.id))

  const isPartialSelected = filteredDocuments.some(doc => selectedIds.has(doc.id)) && !isAllSelected

  // Batch operations using batch API
  const handleBatchDelete = async () => {
    if (selectedIds.size === 0) return
    setBatchLoading(true)
    try {
      await batchDelete(Array.from(selectedIds))
      setSelectedIds(new Set())
    } catch {
      // Error handled by hook
    } finally {
      setBatchLoading(false)
    }
  }

  // Handle web document re-fetch
  const handleRefreshWebDocument = async (doc: KnowledgeDocument) => {
    if (doc.source_type !== 'web') return

    setRefreshingDocId(doc.id)
    try {
      const { refreshWebDocument } = await import('@/apis/knowledge')
      const result = await refreshWebDocument(doc.id)

      if (!result.success) {
        throw new Error(result.error_message || t('document.upload.web.refetchFailed'))
      }

      // Refresh document list to show updated data
      await refresh()
    } catch {
      // Error will be shown via toast in the API layer
    } finally {
      setRefreshingDocId(null)
    }
  }

  // Handle document reindex
  const handleReindexDocument = async (doc: KnowledgeDocument) => {
    setReindexingDocId(doc.id)
    try {
      const { reindexDocument } = await import('@/apis/knowledge')
      const result = await reindexDocument(doc.id)

      if (!result.success) {
        throw new Error(t('document.document.reindexFailed'))
      }

      toast({
        description: t('document.document.reindexSuccess'),
      })

      // Refresh document list after a short delay to allow backend to start processing
      setTimeout(() => {
        if (isMountedRef.current) {
          refresh()
        }
      }, 2000)
    } catch (err) {
      // Use ApiError.errorCode for structured error handling
      let errorMessage = t('document.document.reindexFailed')
      if (err instanceof Error) {
        // Check if it's an ApiError with errorCode for structured error handling
        const apiError = err as { errorCode?: string; message: string }
        if (apiError.errorCode === 'EXCEL_FILE_SIZE_EXCEEDED') {
          // Format: EXCEL_FILE_SIZE_EXCEEDED|extension|limit|size
          const parts = apiError.message.split('|')
          if (parts.length === 4) {
            errorMessage = t('document.document.excelFileSizeExceeded', {
              extension: parts[1],
              limit: parts[2],
              size: parts[3],
            })
          }
        } else {
          // Use the original error message for other errors
          errorMessage = apiError.message
        }
      }
      toast({
        variant: 'destructive',
        description: errorMessage,
      })
    } finally {
      if (isMountedRef.current) {
        setReindexingDocId(null)
      }
    }
  }

  const longSummary = knowledgeBase.summary?.long_summary

  // Folder CRUD handlers
  const handleCreateFolder = async (parentId: number) => {
    setCreateFolderParentId(parentId)
    setShowCreateFolder(true)
  }

  const handleCreateFolderSubmit = async (name: string) => {
    await createFolder({ name, parent_id: createFolderParentId })
    setShowCreateFolder(false)
    refresh()
  }

  const handleRenameFolder = (folderId: number, currentName: string) => {
    setRenamingFolder({ id: folderId, name: currentName })
  }

  const handleRenameFolderSubmit = async (name: string) => {
    if (!renamingFolder) return
    await updateFolder(renamingFolder.id, { name })
    setRenamingFolder(null)
    refresh()
  }

  const handleDeleteFolderClick = (folderId: number, folderName: string) => {
    setDeletingFolder({ id: folderId, name: folderName })
  }

  const handleDeleteFolderConfirm = async () => {
    if (!deletingFolder) return
    await deleteFolder(deletingFolder.id)
    setDeletingFolder(null)
    refresh()
  }

  // Document move handlers
  const handleMoveDocument = useCallback((doc: KnowledgeDocument) => {
    setMovingDoc(doc)
  }, [])

  const handleMoveConfirm = useCallback(
    async (targetFolderId: number) => {
      if (!movingDoc) return
      setIsMovingDoc(true)
      try {
        const success = await moveDocument(movingDoc.id, targetFolderId)
        if (success) {
          setMovingDoc(null)
          refresh()
          fetchFolders()
        }
      } finally {
        setIsMovingDoc(false)
      }
    },
    [movingDoc, moveDocument, refresh, fetchFolders]
  )

  // Knowledge base type info
  const isNotebook = (knowledgeBase.kb_type || 'notebook') === 'notebook'
  // Check if RAG is configured (has retriever and embedding model)
  const ragConfigured = !!(
    knowledgeBase.retrieval_config?.retriever_name &&
    knowledgeBase.retrieval_config?.embedding_config?.model_name
  )

  return (
    <div className="space-y-4">
      {/* Header - Wegent style */}
      <div className="flex items-center gap-3">
        {onBack && (
          <button
            onClick={onBack}
            className="p-1.5 rounded-md text-text-muted hover:text-text-primary hover:bg-surface transition-colors"
          >
            <ArrowLeft className="w-5 h-5" />
          </button>
        )}
        {/* Type icon - based on current kb type */}
        {isNotebook ? (
          <BookOpen className="w-5 h-5 text-primary flex-shrink-0" />
        ) : (
          <Database className="w-5 h-5 text-text-secondary flex-shrink-0" />
        )}
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-1.5">
            {/* Group name prefix with click handler */}
            {groupInfo && (
              <>
                <button
                  onClick={() => onGroupClick?.(groupInfo.groupId, groupInfo.groupType)}
                  className="text-base font-medium text-text-secondary hover:text-primary transition-colors truncate max-w-[120px]"
                  title={groupInfo.groupName}
                >
                  {groupInfo.groupName}
                </button>
                <span className="text-text-muted">/</span>
              </>
            )}
            <h2 className="text-base font-medium text-text-primary truncate">
              {knowledgeBase.name}
            </h2>
            {/* Summary tooltip - next to title (only show if not failed) */}
            {longSummary && !isSummaryFailed && (
              <TooltipProvider>
                <Tooltip delayDuration={200}>
                  <TooltipTrigger asChild>
                    <button className="flex-shrink-0 p-0.5 rounded text-text-muted hover:text-primary hover:bg-surface transition-colors">
                      <Info className="w-4 h-4" />
                    </button>
                  </TooltipTrigger>
                  <TooltipContent side="bottom" align="start" className="max-w-md">
                    <p className="text-sm leading-relaxed">{longSummary}</p>
                  </TooltipContent>
                </Tooltip>
              </TooltipProvider>
            )}
            {/* Summary failed warning - with retry button */}
            {isSummaryFailed && (
              <TooltipProvider>
                <Tooltip delayDuration={200}>
                  <TooltipTrigger asChild>
                    <button className="flex-shrink-0 p-0.5 rounded text-amber-500 hover:bg-surface transition-colors">
                      <AlertTriangle className="w-4 h-4" />
                    </button>
                  </TooltipTrigger>
                  <TooltipContent side="bottom" align="start" className="max-w-md">
                    <p className="text-sm leading-relaxed">
                      {summaryError || t('chatPage.summaryFailedHint')}
                    </p>
                  </TooltipContent>
                </Tooltip>
              </TooltipProvider>
            )}
            {isSummaryFailed && (
              <Button
                variant="ghost"
                size="sm"
                onClick={handleRetrySummary}
                disabled={isSummaryRetrying}
                className="h-6 px-2 text-xs text-amber-500 hover:text-amber-600"
              >
                <RefreshCw className={`w-3 h-3 mr-1 ${isSummaryRetrying ? 'animate-spin' : ''}`} />
                {isSummaryRetrying ? t('chatPage.summaryRetrying') : t('chatPage.summaryRetry')}
              </Button>
            )}
          </div>
          {knowledgeBase.description && (
            <p className="text-xs text-text-muted truncate">{knowledgeBase.description}</p>
          )}
        </div>
        {/* Header actions (e.g., tabs) */}
        {headerActions}
      </div>

      {/* Search bar and action buttons */}
      <div className="flex items-center gap-3 flex-wrap">
        {/* Search - inline for normal mode, popover for compact mode */}
        {compact ? (
          <div className="relative">
            <Button
              variant="outline"
              size="sm"
              onClick={() => setShowSearchPopover(!showSearchPopover)}
              className={searchQuery ? 'border-primary' : ''}
            >
              <Search className="w-4 h-4" />
              {searchQuery && (
                <span className="ml-1 max-w-[60px] truncate text-xs">{searchQuery}</span>
              )}
            </Button>
            {showSearchPopover && (
              <div className="absolute top-full left-0 mt-1 z-50 bg-base border border-border rounded-md shadow-lg p-2 min-w-[240px]">
                <div className="relative">
                  <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-text-muted" />
                  <input
                    type="text"
                    autoFocus
                    className="w-full h-9 pl-9 pr-3 text-sm bg-surface border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary"
                    placeholder={t('document.document.search')}
                    value={searchQuery}
                    onChange={e => setSearchQuery(e.target.value)}
                    onKeyDown={e => {
                      if (e.key === 'Escape') {
                        setShowSearchPopover(false)
                      }
                    }}
                    onBlur={() => {
                      // Delay to allow click events to fire
                      setTimeout(() => setShowSearchPopover(false), 150)
                    }}
                  />
                </div>
              </div>
            )}
          </div>
        ) : (
          <div className="relative flex-1 max-w-md">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-text-muted" />
            <input
              type="text"
              className="w-full h-9 pl-9 pr-3 text-sm bg-surface border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary"
              placeholder={t('document.document.search')}
              value={searchQuery}
              onChange={e => setSearchQuery(e.target.value)}
            />
          </div>
        )}
        {/* Spacer to push buttons to the right */}
        <div className="flex-1" />

        {/* Refresh list button */}
        <TooltipProvider>
          <Tooltip delayDuration={200}>
            <TooltipTrigger asChild>
              <Button variant="outline" size="sm" onClick={refresh} disabled={loading}>
                <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />
              </Button>
            </TooltipTrigger>
            <TooltipContent>
              <p>{t('common:actions.refresh')}</p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>

        {/* Retrieval test button */}
        <TooltipProvider>
          <Tooltip delayDuration={200}>
            <TooltipTrigger asChild>
              <Button variant="outline" size="sm" onClick={() => setShowRetrievalTest(true)}>
                <Target className="w-4 h-4" />
              </Button>
            </TooltipTrigger>
            <TooltipContent>
              <p>{t('document.retrievalTest.button')}</p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>

        {/* Create folder button */}
        {canUpload && (
          <Button
            variant="outline"
            className="h-11 min-w-[44px]"
            onClick={() => handleCreateFolder(0)}
          >
            <FolderPlus className="w-4 h-4 mr-1" />
            {t('document.folder.create')}
          </Button>
        )}

        {/* Upload button */}
        {canUpload && (
          <Button variant="primary" size="sm" onClick={() => setShowUpload(true)}>
            <Upload className="w-4 h-4 mr-1" />
            {t('document.document.upload')}
          </Button>
        )}
      </div>

      {/* Document List */}
      {loading && documents.length === 0 ? (
        <div className="flex items-center justify-center py-12">
          <Spinner />
        </div>
      ) : showLoadError ? (
        <div className="flex flex-col items-center justify-center py-12 text-text-secondary">
          <p>{error}</p>
          <Button variant="outline" className="mt-4" onClick={refresh}>
            {t('common:actions.retry')}
          </Button>
        </div>
      ) : filteredDocuments.length > 0 || folders.length > 0 ? (
        <>
          {/* Batch action bar - shown when items are selected (not in notebook mode where selection is for context injection) */}
          {canManageAllDocuments && selectedIds.size > 0 && !onSelectionChange && (
            <div
              className={`flex items-center gap-3 ${compact ? 'px-2 py-2' : 'px-4 py-2.5'} bg-primary/5 border border-primary/20 rounded-lg`}
            >
              <span className="text-sm text-text-primary">
                {t('document.document.batch.selected', { count: selectedIds.size })}
              </span>
              <div className="flex-1" />
              <Button
                variant="destructive"
                size="sm"
                onClick={handleBatchDelete}
                disabled={batchLoading}
              >
                <Trash2 className="w-4 h-4 mr-1" />
                {compact ? '' : t('document.document.batch.delete')}
              </Button>
            </div>
          )}

          {/* Compact mode: Card layout */}
          {compact ? (
            <div className="space-y-2">
              {/* Select all control bar for notebook mode */}
              {onSelectionChange && filteredDocuments.length > 0 && (
                <div className="flex items-center gap-2 px-2 py-1.5 text-xs text-text-muted">
                  <button
                    onClick={() => handleSelectAll(!isAllSelected)}
                    className="flex items-center gap-1.5 hover:text-text-primary transition-colors"
                  >
                    {isAllSelected ? (
                      <CheckSquare className="w-3.5 h-3.5 text-primary" />
                    ) : (
                      <Square className="w-3.5 h-3.5" />
                    )}
                    <span>{t('document.document.batch.selectAll')}</span>
                  </button>
                  <span className="text-text-muted">
                    ({filteredDocuments.filter(doc => selectedIds.has(doc.id)).length}/
                    {filteredDocuments.length})
                  </span>
                </div>
              )}
              <FolderTree
                folders={folders}
                documents={filteredDocuments}
                compact={true}
                onViewDetail={setViewingDoc}
                onEdit={setEditingDoc}
                onDelete={setDeletingDoc}
                onRefresh={handleRefreshWebDocument}
                onReindex={handleReindexDocument}
                onMove={handleMoveDocument}
                refreshingDocId={refreshingDocId}
                reindexingDocId={reindexingDocId}
                canManage={canManageDocument}
                canSelect={canSelectDocument}
                selectedIds={selectedIds}
                onSelect={handleSelectDoc}
                ragConfigured={ragConfigured}
                onCreateFolder={canUpload ? handleCreateFolder : undefined}
                onRenameFolder={canUpload ? handleRenameFolder : undefined}
                onDeleteFolder={canUpload ? handleDeleteFolderClick : undefined}
                canManageFolders={canUpload}
                sortField={sortField}
                sortOrder={sortOrder}
              />
            </div>
          ) : (
            /* Normal mode: Table layout with folder tree - single bordered container */
            <div className="border border-border rounded-lg overflow-x-auto">
              {/* Inner container - width determined by content, background covers all */}
              <div className="bg-base min-w-[880px] w-fit">
                {/* Table header */}
                <div className="flex items-center gap-4 px-4 py-2.5 bg-surface text-xs text-text-muted font-medium border-b border-border">
                  {/* Checkbox for select all */}
                  {canManageAllDocuments && (
                    <div className="flex-shrink-0">
                      <Checkbox
                        checked={isPartialSelected ? 'indeterminate' : isAllSelected}
                        onCheckedChange={handleSelectAll}
                        className="data-[state=checked]:bg-primary data-[state=checked]:border-primary"
                      />
                    </div>
                  )}
                  {/* Icon + Name column header */}
                  <div
                    ref={nameColumnRef}
                    className={`relative flex items-center gap-2 ${nameColumnWidth ? 'flex-shrink-0' : 'flex-1 min-w-[200px]'}`}
                    style={nameColumnWidth ? { width: `${nameColumnWidth}px` } : undefined}
                  >
                    {/* Icon placeholder */}
                    <div className="w-4 h-4 flex-shrink-0" />
                    <button
                      type="button"
                      className="cursor-pointer hover:text-text-primary select-none"
                      onClick={() => handleSort('name')}
                    >
                      {t('document.document.columns.name')}
                      <SortIcon field="name" />
                    </button>
                    {/* Column resize handle */}
                    <div
                      className="absolute top-0 right-0 bottom-0 w-3 cursor-col-resize z-10 group/resize flex items-center justify-center"
                      onMouseDown={handleNameResizeMouseDown}
                      onClick={e => e.stopPropagation()}
                    >
                      <div className="w-0.5 h-3/4 rounded-full bg-border group-hover/resize:bg-primary/50 transition-colors" />
                    </div>
                  </div>
                  {/* Spacer to match DocumentItem edit button area */}
                  <div className="w-7 flex-shrink-0" />
                  <div className="w-20 flex-shrink-0 text-center">
                    {t('document.document.columns.type')}
                  </div>
                  <button
                    type="button"
                    className="w-20 flex-shrink-0 text-center cursor-pointer hover:text-text-primary select-none"
                    onClick={() => handleSort('size')}
                  >
                    {t('document.document.columns.size')}
                    <SortIcon field="size" />
                  </button>
                  {/* Creator column header */}
                  <div className="w-24 flex-shrink-0 text-center">
                    {t('document.document.columns.createdBy')}
                  </div>
                  <button
                    type="button"
                    className="w-40 flex-shrink-0 text-center cursor-pointer hover:text-text-primary select-none"
                    onClick={() => handleSort('createdAt')}
                  >
                    {t('document.document.columns.date')}
                    <SortIcon field="createdAt" />
                  </button>
                  {/* Updated date column header */}
                  <button
                    type="button"
                    className="w-40 flex-shrink-0 text-center cursor-pointer hover:text-text-primary select-none"
                    onClick={() => handleSort('updatedAt')}
                  >
                    {t('document.document.columns.updatedAt')}
                    <SortIcon field="updatedAt" />
                  </button>
                  <div className="w-24 flex-shrink-0 text-center">
                    {t('document.document.columns.indexStatus')}
                  </div>
                  {canManageAnyDocuments && (
                    <div className="w-20 flex-shrink-0 text-center">
                      {t('document.document.columns.actions')}
                    </div>
                  )}
                </div>
                {/* Document rows with folder tree - no extra border */}
                <FolderTree
                  folders={folders}
                  documents={filteredDocuments}
                  compact={false}
                  withBorder={false}
                  onViewDetail={setViewingDoc}
                  onEdit={setEditingDoc}
                  onDelete={setDeletingDoc}
                  onRefresh={handleRefreshWebDocument}
                  onReindex={handleReindexDocument}
                  onMove={handleMoveDocument}
                  refreshingDocId={refreshingDocId}
                  reindexingDocId={reindexingDocId}
                  canManage={canManageDocument}
                  canSelect={doc => canSelectDocument(doc) && canManageAllDocuments}
                  selectedIds={selectedIds}
                  onSelect={handleSelectDoc}
                  ragConfigured={ragConfigured}
                  nameColumnWidth={nameColumnWidth ?? undefined}
                  onCreateFolder={canUpload ? handleCreateFolder : undefined}
                  onRenameFolder={canUpload ? handleRenameFolder : undefined}
                  onDeleteFolder={canUpload ? handleDeleteFolderClick : undefined}
                  canManageFolders={canUpload}
                  sortField={sortField}
                  sortOrder={sortOrder}
                />
              </div>
            </div>
          )}
          {/* Overlay during column resize to prevent pointer event interference */}
          {isColumnResizing && (
            <div className="fixed inset-0 z-50" style={{ cursor: 'col-resize' }} />
          )}
        </>
      ) : searchQuery ? (
        <div className="flex flex-col items-center justify-center py-12 text-text-secondary">
          <FileText className="w-12 h-12 mb-4 opacity-50" />
          <p>{t('document.document.noResults')}</p>
        </div>
      ) : canUpload ? (
        <div className="flex flex-col items-center justify-center py-16 text-text-secondary">
          <FileUp className="w-16 h-16 mb-4 text-text-muted opacity-60" />
          <p className="text-base text-text-primary mb-2">{t('document.document.emptyHint')}</p>
        </div>
      ) : (
        <div className="flex flex-col items-center justify-center py-12 text-text-secondary">
          <FileText className="w-12 h-12 mb-4 opacity-50" />
          <p>{t('document.document.empty')}</p>
        </div>
      )}

      {/* Auto-open document from ?doc= URL parameter (wrapped in Suspense for useSearchParams) */}
      <Suspense fallback={null}>
        <DocAutoOpener documents={documents} loading={loading} onOpen={setViewingDoc} />
      </Suspense>

      {/* Dialogs */}
      <DocumentDetailDialog
        open={!!viewingDoc}
        onOpenChange={open => !open && setViewingDoc(null)}
        document={viewingDoc}
        knowledgeBaseId={knowledgeBase.id}
        kbType={knowledgeBase.kb_type}
        canEdit={viewingDoc ? canManageDocument(viewingDoc) : false}
        knowledgeBaseName={knowledgeBase.name}
        knowledgeBaseNamespace={knowledgeBase.namespace || 'default'}
        isOrganization={isOrganization}
      />
      <DocumentUpload
        open={showUpload}
        onOpenChange={setShowUpload}
        onUploadComplete={handleUploadComplete}
        onTableAdd={handleTableAdd}
        onWebAdd={handleWebAdd}
        kbType={knowledgeBase.kb_type}
        currentDocumentCount={documents.length}
        folderId={selectedUploadFolderId}
        folderOptions={folderOptions}
        onFolderChange={setSelectedUploadFolderId}
      />

      <EditDocumentDialog
        open={!!editingDoc}
        onOpenChange={open => !open && setEditingDoc(null)}
        document={editingDoc}
        onSuccess={() => {
          setEditingDoc(null)
          refresh()
        }}
      />

      <DeleteDocumentDialog
        open={!!deletingDoc}
        onOpenChange={open => !open && setDeletingDoc(null)}
        document={deletingDoc}
        onConfirm={handleDelete}
        loading={loading}
      />

      <RetrievalTestDialog
        open={showRetrievalTest}
        onOpenChange={setShowRetrievalTest}
        knowledgeBase={knowledgeBase}
      />

      {/* Folder dialogs */}
      <CreateFolderDialog
        open={showCreateFolder}
        onOpenChange={setShowCreateFolder}
        onSubmit={handleCreateFolderSubmit}
      />

      <CreateFolderDialog
        open={!!renamingFolder}
        onOpenChange={open => !open && setRenamingFolder(null)}
        onSubmit={handleRenameFolderSubmit}
        initialName={renamingFolder?.name}
      />

      <DeleteFolderDialog
        open={!!deletingFolder}
        onOpenChange={open => !open && setDeletingFolder(null)}
        folderName={deletingFolder?.name || ''}
        onConfirm={handleDeleteFolderConfirm}
      />

      <MoveDocumentDialog
        open={!!movingDoc}
        onOpenChange={open => !open && setMovingDoc(null)}
        documentName={movingDoc?.name || ''}
        folders={folderOptions}
        currentFolderId={movingDoc?.folder_id ?? 0}
        onConfirm={handleMoveConfirm}
        isSubmitting={isMovingDoc}
      />
    </div>
  )
}
