import React, { useCallback, useEffect, useState, useMemo, useRef } from 'react'
import IndexingModalWithMode from '../../components/IndexingModalWithMode'
import { PDFPreview } from '../../components/PDFPreview'
import { DragDropUpload } from '../../components/DragDropUpload'
import { GlobalDragDropOverlay } from '../../components/GlobalDragDropOverlay'
import {
    AppSettings,
    DEFAULT_MODELS,
    DEFAULT_SETTINGS,
    IndexingConfig,
    KnowledgeFile,
    ModelConfig,
    ModelType,
    RawFile,
    KnowledgeGroup,
} from '../../types'
import { readFile, formatBytes } from '../../utils/fileUtils'
import { useLanguage } from '../../contexts/LanguageContext'
import { useToast } from '../../contexts/ToastContext'
import { userSettingService } from '../../services/userSettingService'
import { uploadService } from '../../services/uploadService'
import { knowledgeBaseService } from '../../services/knowledgeBaseService'
import { knowledgeGroupService } from '../../services/knowledgeGroupService'
import { useConfirm } from '../../contexts/ConfirmContext'
import { SettingsDrawer } from '../../components/SettingsDrawer'
import { FileGroupTags } from '../../components/FileGroupTags'
import { ChunkInfoDrawer } from '../../components/ChunkInfoDrawer'
import {
    Search,
    Filter,
    Upload,
    FileText,
    Image as ImageIcon,
    FileType,
    CheckCircle2,
    CircleDashed,
    RefreshCw,
    Eye,
    Trash2,
    FolderPlus,
    ChevronLeft,
    ChevronRight,
    LayoutList,
    RotateCcw,
    Settings,
    Info
} from 'lucide-react'
import { KB_ALLOWED_EXTENSIONS, IMAGE_MIME_TYPES, isExtensionAllowed, getSupportedFormatsLabel, DOC_EXTENSIONS, CODE_EXTENSIONS, IMAGE_EXTENSIONS, isFormatSupportedForPreview } from '../../constants/fileSupport'

interface KnowledgeBaseViewProps {
    authToken: string;
    onLogout: () => void;
    modelConfigs?: ModelConfig[];
    onNavigate: (view: any) => void;
    isAdmin?: boolean;
}

export const KnowledgeBaseView: React.FC<KnowledgeBaseViewProps> = (props) => {
    const { authToken, onLogout, modelConfigs = DEFAULT_MODELS, onNavigate, isAdmin = false } = props;
    const { showError, showWarning, showSuccess } = useToast()
    const { confirm } = useConfirm()
    const { t } = useLanguage()

    // Data State
    const [files, setFiles] = useState<KnowledgeFile[]>([])
    const [groups, setGroups] = useState<KnowledgeGroup[]>([])
    const [settings, setSettings] = useState<AppSettings>(DEFAULT_SETTINGS)
    const [isLoadingSettings, setIsLoadingSettings] = useState(true)
    const [isLoadingFiles, setIsLoadingFiles] = useState(true) // 添加文件加载状态

    // UI State
    const [isSettingsOpen, setIsSettingsOpen] = useState(false)
    const [pdfPreview, setPdfPreview] = useState<{ fileId: string; fileName: string } | null>(null)
    const [isIndexingModalOpen, setIsIndexingModalOpen] = useState(false)
    const [pendingFiles, setPendingFiles] = useState<RawFile[]>([])
    const [fileInputRef] = useState<React.RefObject<HTMLInputElement>>(React.createRef())

    // State to track if modal should be opened
    const [shouldOpenModal, setShouldOpenModal] = useState(false)

    // Effect to open modal when pending files are set
    useEffect(() => {
        if (shouldOpenModal && pendingFiles.length > 0) {
            setIsIndexingModalOpen(true);
            setShouldOpenModal(false);
        }
    }, [shouldOpenModal, pendingFiles.length]);

    // Filter & Pagination State
    const [filterName, setFilterName] = useState('')
    const [filterGroup, setFilterGroup] = useState('all')
    const [filterStatus, setFilterStatus] = useState<'all' | 'ready' | 'indexing' | 'failed'>('all')
    const [currentPage, setCurrentPage] = useState(1)
    const pageSize = 20
    const [chunkDrawer, setChunkDrawer] = useState<{ isOpen: boolean; fileId: string; fileName: string } | null>(null)

    // Auto-refresh state
    const [isAutoRefreshEnabled, setIsAutoRefreshEnabled] = useState(true)
    const [autoRefreshInterval, setAutoRefreshInterval] = useState<number>(5000) // 5 seconds default

    // --- データ取得 ---

    const fetchAndSetSettings = useCallback(async () => {
        if (!authToken) return
        try {
            // 管理者の場合はグローバル設定を取得、そうでない場合は個人設定を取得
            // ただし、検索パラメータ自体はグローバル設定から来るべきなので、
            // ここでは表示・編集用に、管理者はグローバル設定を直接触るようにする。
            const settingsData = isAdmin
                ? await userSettingService.getGlobal(authToken)
                : await userSettingService.get(authToken);

            setSettings({ ...DEFAULT_SETTINGS, ...settingsData })
        } catch (error) {
            console.error('Failed to fetch settings:', error)
            setSettings(DEFAULT_SETTINGS)
        } finally {
            setIsLoadingSettings(false)
        }
    }, [authToken, isAdmin])

    const fetchAndSetFiles = useCallback(async () => {
        if (!authToken) return
        try {
            const remoteFiles = await knowledgeBaseService.getAll(authToken)
            setFiles(remoteFiles)
        } catch (error) {
            console.error('Failed to fetch files:', error)
        } finally {
            setIsLoadingFiles(false) // ファイル読み込み完了
        }
    }, [authToken])

    const fetchAndSetGroups = useCallback(async () => {
        if (!authToken) return
        try {
            const remoteGroups = await knowledgeGroupService.getGroups()
            setGroups(remoteGroups)
        } catch (error) {
            console.error('Failed to fetch groups:', error)
        }
    }, [authToken])

    useEffect(() => {
        if (authToken) {
            fetchAndSetSettings()
            fetchAndSetFiles()
            fetchAndSetGroups()
        }
    }, [authToken, fetchAndSetSettings, fetchAndSetFiles, fetchAndSetGroups])

    // --- ハンドラー ---

    // プレビュー変換に対応しているか確認
    const isSupportedForPreview = (file: KnowledgeFile) => {
        return isFormatSupportedForPreview(file.name);
    };

    const handleUpdateSettings = async (newSettings: AppSettings) => {
        if (!authToken) return
        try {
            if (isAdmin) {
                await userSettingService.updateGlobal(authToken, newSettings)
            } else {
                await userSettingService.update(authToken, newSettings)
            }
            setSettings(newSettings)
        } catch (error: any) {
            console.error('Failed to update settings:', error)
            const detail = error.response?.data?.message
            const errorMessage = Array.isArray(detail) ? detail.join(', ') : detail || error.message || t('mmErrorTitle')
            showError(`${t('mmErrorTitle')}: ${errorMessage}`)
        }
    }

    const handleFileUpload = async (fileList: FileList) => {
        console.log('DEBUG: handleFileUpload called with', fileList.length, 'files');

        // Log all files received from the file input
        for (let i = 0; i < fileList.length; i++) {
            const file = fileList[i];
            console.log('DEBUG: File', i, 'details:', {
                name: file.name,
                size: file.size,
                type: file.type,
                lastModified: file.lastModified
            });
        }

        if (!authToken) {
            showWarning(t('loginRequired'))
            return
        }

        const MAX_FILE_SIZE = 104857600;
        const MAX_SIZE_MB = 100;
        const rawFiles: RawFile[] = []
        const errors: string[] = []

        console.log('DEBUG: About to start processing', fileList.length, 'files');

        // Process each file sequentially using array methods to avoid potential loop issues
        const filesArray = Array.from(fileList); // Convert FileList to Array

        for (let i = 0; i < filesArray.length; i++) {
            console.log('DEBUG: Loop iteration', i, 'starting');
            const file = filesArray[i];
            console.log('DEBUG: Processing file', i, ':', file.name, 'size:', file.size, 'type:', file.type);

            const extension = file.name.split('.').pop() || ''

            if (!isExtensionAllowed(extension, 'kb')) {
                errors.push(t('unsupportedFileType', file.name, extension))
                console.log('DEBUG: File rejected due to type restriction:', file.name, 'extension:', extension);
                console.log('DEBUG: Loop iteration', i, 'completed due to type check');
                continue
            }

            if (file.size > MAX_FILE_SIZE) {
                errors.push(t('fileSizeLimitExceeded', file.name, formatBytes(file.size), MAX_SIZE_MB))
                console.log('DEBUG: File rejected due to size limit:', file.name);
                console.log('DEBUG: Loop iteration', i, 'completed due to size check');
                continue;
            }

            try {
                console.log('DEBUG: Attempting to read file:', file.name);
                const rawFile = await readFile(file)
                rawFiles.push(rawFile)
                console.log('DEBUG: Successfully added file to rawFiles:', file.name);
                console.log('DEBUG: Loop iteration', i, 'completed successfully');
            } catch (error) {
                console.error(`Error reading file ${file.name}:`, error);
                errors.push(`${file.name} - ${t('readingFailed')}`);
                console.log('DEBUG: Failed to read file:', file.name);
                console.log('DEBUG: Loop iteration', i, 'completed due to error in readFile');
            }
        }

        console.log('DEBUG: Finished processing all files');
        console.log('DEBUG: Final rawFiles array:', rawFiles.map(f => f.name));
        console.log('DEBUG: Errors array:', errors);
        console.log('DEBUG: Number of valid files:', rawFiles.length);
        console.log('DEBUG: Number of errors:', errors.length);

        if (errors.length > 0) showError(`${t('uploadErrors')}:\n${errors.join('\n')}`);
        if (rawFiles.length === 0) {
            console.log('DEBUG: No valid files to process, returning early');
            return;
        }
        if (errors.length > 0 && rawFiles.length > 0) showWarning(t('uploadWarning').replace('$1', `${rawFiles.length}`).replace('$2', `${errors.length}`));

        console.log('DEBUG: Setting pendingFiles with', rawFiles.length, 'files');
        setPendingFiles(rawFiles);
        console.log('DEBUG: Current pendingFiles state:', pendingFiles.length); // This won't reflect the update yet
        setShouldOpenModal(true);
        console.log('DEBUG: Set shouldOpenModal to true');
    }

    const handleRetryFile = async (fileId: string) => {
        if (!authToken) return

        try {
            showSuccess(t('retrying'))
            await knowledgeBaseService.retryFile(fileId, authToken)
            showSuccess(t('retrySuccess'))
            await fetchAndSetFiles()
        } catch (error) {
            console.error('Failed to retry file:', error)
            showError(t('retryFailed'))
        }
    }


    const handleConfirmIndexing = async (config: IndexingConfig) => {
        console.log('DEBUG: handleConfirmIndexing called with config and', pendingFiles.length, 'pending files');

        if (!authToken) {
            console.log('DEBUG: No auth token, returning');
            return
        }
        let hasSuccess = false

        for (const rawFile of pendingFiles) {
            console.log('DEBUG: Uploading file:', rawFile.name);
            try {
                await uploadService.uploadFileWithConfig(rawFile.file, config, authToken)
                hasSuccess = true
                console.log('DEBUG: Successfully uploaded file:', rawFile.name);
            } catch (error) {
                console.error(`Error uploading file ${rawFile.name}:`, error)
                showError(`${t('uploadFailed')}: ${rawFile.name} - ${error.message}`)
            }
        }
        if (hasSuccess) await fetchAndSetFiles()
        console.log('DEBUG: Clearing pending files');
        setPendingFiles([])
        setIsIndexingModalOpen(false)
        console.log('DEBUG: Closed indexing modal');
    }

    const handleRemoveFile = async (id: string) => {
        if (!(await confirm(t('confirmDeleteFile')))) return
        if (!authToken) return
        try {
            await knowledgeBaseService.deleteFile(id, authToken)
            setFiles(prev => prev.filter(f => f.id !== id))
            showSuccess(t('fileDeleted'))
        } catch (error) {
            console.error('Failed to delete file:', error)
            showError(`${t('deleteFailed')}: ` + error.message)
        }
    }

    const handleClearAll = async () => {
        if (!(await confirm(t('confirmClearKB')))) return
        if (!authToken) return
        try {
            await knowledgeBaseService.clearAll(authToken)
            setFiles([])
            showSuccess(t('kbCleared'))
        } catch (error) {
            console.error('Failed to clear knowledge base:', error)
            showError(`${t('clearFailed')}: ` + error.message)
        }
    }

    const handleFileGroupsChange = (fileId: string, groupIds: string[]) => {
        setFiles(prev => prev.map(file =>
            file.id === fileId
                ? { ...file, groups: groups.filter(g => groupIds.includes(g.id)) }
                : file
        ))
    }

    // --- ヘルパー ---

    const getFileIcon = (file: KnowledgeFile) => {
        if (file.type.startsWith('image/')) return <ImageIcon className="w-5 h-5 text-purple-500" />;
        if (file.type === 'application/pdf') return <FileType className="w-5 h-5 text-red-500" />;
        return <FileText className="w-5 h-5 text-blue-500" />;
    };

    // --- フィルタリングとページネーションのロジック ---

    const filteredFiles = useMemo(() => {
        return files.filter(file => {
            const matchName = file.name.toLowerCase().includes(filterName.toLowerCase());
            const matchGroup = filterGroup === 'all' || file.groups?.some(g => g.id === filterGroup);
            const matchStatus = filterStatus === 'all' ||
                (filterStatus === 'ready' && (file.status === 'ready' || file.status === 'vectorized')) ||
                (filterStatus === 'indexing' && (file.status === 'indexing' || file.status === 'pending' || file.status === 'extracted')) ||
                (filterStatus === 'failed' && (file.status === 'failed' || file.status === 'error'));
            return matchName && matchGroup && matchStatus;
        });
    }, [files, filterName, filterGroup, filterStatus]);

    const totalPages = Math.ceil(filteredFiles.length / pageSize);
    const paginatedFiles = useMemo(() => {
        const start = (currentPage - 1) * pageSize;
        return filteredFiles.slice(start, start + pageSize);
    }, [filteredFiles, currentPage, pageSize]);

    // フィルタが変更されたときにページをリセット
    useEffect(() => {
        setCurrentPage(1);
    }, [filterName, filterGroup, filterStatus]);

    // Auto-refresh functionality for indexing files
    useEffect(() => {
        let intervalId: NodeJS.Timeout | null = null;

        const hasIndexingFiles = () => {
            return files.some(file =>
                file.status === 'pending' ||
                file.status === 'indexing' ||
                file.status === 'extracted' ||
                file.status === 'vectorized'
            );
        };

        const manageAutoRefresh = () => {
            if (intervalId) {
                clearInterval(intervalId);
                intervalId = null;
            }

            if (isAutoRefreshEnabled && hasIndexingFiles()) {
                intervalId = setInterval(() => {
                    fetchAndSetFiles();
                }, autoRefreshInterval);
            }
        };

        // Manage auto-refresh based on current conditions
        manageAutoRefresh();

        // Cleanup on unmount
        return () => {
            if (intervalId) {
                clearInterval(intervalId);
            }
        };
    }, [isAutoRefreshEnabled, files, autoRefreshInterval, fetchAndSetFiles]);


    if (isLoadingSettings) {
        return (
            <div className='flex items-center justify-center min-h-screen bg-slate-50 w-full'>
                <div className='text-blue-600 animate-spin rounded-full h-12 w-12 border-4 border-t-4 border-blue-300'></div>
            </div>
        )
    }

    return (
        <div className='flex flex-col h-full w-full bg-slate-50 overflow-hidden relative'>
            {/* Header */}
            <div className="bg-white border-b border-slate-200 px-6 py-4 flex items-center justify-between shrink-0">
                <div>
                    <h1 className="text-xl font-bold text-slate-800 flex items-center gap-2">
                        <LayoutList className="w-6 h-6 text-blue-600" />
                        <span className="bg-gradient-to-r from-blue-600 to-purple-600 text-transparent bg-clip-text">
                            {t('kbManagement')}
                        </span>
                    </h1>
                    <p className="text-sm text-slate-500 mt-1">{t('kbManagementDesc')}</p>
                </div>
                <div className="flex items-center gap-3">
                    {isAdmin && (
                        <button
                            onClick={() => setIsSettingsOpen(true)}
                            className="flex items-center gap-2 px-4 py-2 bg-white border border-slate-200 text-slate-700 rounded-lg hover:bg-slate-50 transition-colors shadow-sm"
                            title={t('settings')}
                        >
                            <Settings className="w-4 h-4 text-blue-600" />
                            {t('settings')}
                        </button>
                    )}

                    {isAdmin && (
                        <button
                            onClick={handleClearAll}
                            className="flex items-center gap-2 px-4 py-2 bg-white border border-red-200 text-red-600 rounded-lg hover:bg-red-50 transition-colors shadow-sm"
                            title={t('confirmClearKB')}
                        >
                            <Trash2 className="w-4 h-4" />
                            {t('clearAll')}
                        </button>
                    )}
                </div>
            </div>

            {/* フィルタとアクションバー */}
            <div className="px-6 py-4 flex flex-col md:flex-row md:items-center justify-between gap-4 shrink-0">
                <div className="flex flex-wrap items-center gap-3 flex-1">
                    {/* 検索 */}
                    <div className="relative w-full md:w-64">
                        <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
                        <input
                            type="text"
                            placeholder={t('searchPlaceholder')}
                            value={filterName}
                            onChange={(e) => setFilterName(e.target.value)}
                            className="w-full pl-9 pr-4 py-2 bg-white border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500"
                        />
                    </div>

                    {/* グループフィルタ */}
                    <div className="relative w-40">
                        <Filter className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
                        <select
                            value={filterGroup}
                            onChange={(e) => setFilterGroup(e.target.value)}
                            className="w-full pl-9 pr-8 py-2 bg-white border border-slate-200 rounded-lg text-sm appearance-none focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500"
                        >
                            <option value="all">{t('allGroups')}</option>
                            {groups.map(g => (
                                <option key={g.id} value={g.id}>{g.name}</option>
                            ))}
                        </select>
                    </div>

                    {/* ステータスフィルタ */}
                    <div className="w-32">
                        <select
                            value={filterStatus}
                            onChange={(e) => setFilterStatus(e.target.value as any)}
                            className="w-full px-3 py-2 bg-white border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500"
                        >
                            <option value="all">{t('allStatus')}</option>
                            <option value="ready">{t('statusReadyFragment')}</option>
                            <option value="indexing">{t('statusIndexingFragment')}</option>
                            <option value="failed">{t('statusFailedFragment')}</option>
                        </select>
                    </div>

                    {/* Auto-refresh toggle */}
                    <div className="flex items-center gap-2">
                        <label className="text-sm text-slate-600">{t('autoRefresh')}</label>
                        <button
                            type="button"
                            onClick={() => setIsAutoRefreshEnabled(!isAutoRefreshEnabled)}
                            className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors focus:outline-none ${isAutoRefreshEnabled ? 'bg-blue-600' : 'bg-slate-300'
                                }`}
                        >
                            <span
                                className={`inline-block h-3 w-3 transform rounded-full bg-white transition-transform ${isAutoRefreshEnabled ? 'translate-x-5' : 'translate-x-1'
                                    }`}
                            />
                        </button>
                    </div>

                    {/* Auto-refresh interval selector - only show when enabled */}
                    {isAutoRefreshEnabled && (
                        <div className="flex items-center gap-2">
                            <label className="text-sm text-slate-600">{t('refreshInterval')}</label>
                            <select
                                value={autoRefreshInterval}
                                onChange={(e) => setAutoRefreshInterval(Number(e.target.value))}
                                className="px-2 py-1 text-sm bg-white border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500"
                            >
                                <option value={2000}>2s</option>
                                <option value={5000}>5s</option>
                                <option value={10000}>10s</option>
                                <option value={30000}>30s</option>
                            </select>
                        </div>
                    )}
                </div>

                {/* 上传按钮组 - 保持两个上传选项 */}
                <div className="flex items-center gap-3">
                    <input
                        type="file"
                        ref={fileInputRef}
                        onChange={(e) => {
                            if (e.target.files && e.target.files.length > 0) handleFileUpload(e.target.files)
                            if (fileInputRef.current) fileInputRef.current.value = ''
                        }}
                        multiple
                        className="hidden"
                        accept={KB_ALLOWED_EXTENSIONS.map(ext => `.${ext}`).join(',') + ',' + IMAGE_MIME_TYPES.join(',')}
                    />
                    {isAdmin && (
                        <div className="flex items-center gap-2">
                            <div className="group relative">
                                <Info className="w-5 h-5 text-slate-400 cursor-help hover:text-blue-500 transition-colors" />
                                <div className="absolute bottom-full right-0 mb-2 w-max bg-slate-900 text-white text-xs px-3 py-2 rounded-lg opacity-0 group-hover:opacity-100 transition-all pointer-events-none z-[100] shadow-xl border border-slate-700 whitespace-nowrap">
                                    {t('supportedFormatsInfo')}
                                </div>
                            </div>
                            <button
                                onClick={() => fileInputRef.current?.click()}
                                className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg shadow-sm transition-colors font-medium"
                            >
                                <Upload className="w-4 h-4" />
                                {t('uploadFile')}
                            </button>
                        </div>
                    )}
                </div>
            </div>

            {/* 全局拖拽上传覆盖层 - 只在拖拽文件到页面时显示 */}
            <GlobalDragDropOverlay
                onFilesSelected={handleFileUpload}
                isAdmin={isAdmin}
            />

            {/* リスト表示 */}
            <div className="flex-1 overflow-hidden px-6 pb-4 flex flex-col">
                <div className="bg-white border border-slate-200 rounded-lg shadow-sm flex flex-col h-full overflow-hidden">
                    {/* リストヘッダー */}
                    <div className="grid grid-cols-12 gap-4 px-6 py-3 bg-slate-50 border-b border-slate-200 text-xs font-semibold text-slate-500 uppercase tracking-wider shrink-0">
                        <div className="col-span-4">{t('fileName')}</div>
                        <div className="col-span-2">{t('size')}</div>
                        <div className="col-span-2">{t('status')}</div>
                        <div className="col-span-2">{t('groups')}</div>
                        <div className="col-span-2 text-right">{t('actions')}</div>
                    </div>

                    {/* リストアイテム */}
                    <div className="flex-1 overflow-y-auto">
                        {paginatedFiles.length > 0 ? (
                            paginatedFiles.map((file) => (
                                <div key={file.id} className="grid grid-cols-12 gap-4 px-6 py-4 border-b border-slate-100 last:border-0 hover:bg-slate-50 transition-colors items-center group">
                                    <div className="col-span-4 flex items-center gap-3 min-w-0">
                                        {getFileIcon(file)}
                                        <button
                                            onClick={() => setChunkDrawer({ isOpen: true, fileId: file.id, fileName: file.name })}
                                            className="truncate font-medium text-blue-600 hover:text-blue-800 hover:underline text-left"
                                            title={file.name}
                                        >
                                            {file.name}
                                        </button>
                                    </div>
                                    <div className="col-span-2 text-sm text-slate-500">
                                        {formatBytes(file.size)}
                                    </div>
                                    <div className="col-span-2">
                                        <span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium ${file.status === 'ready' || file.status === 'vectorized'
                                            ? 'bg-emerald-50 text-emerald-700'
                                            : (file.status === 'failed' || file.status === 'error')
                                                ? 'bg-red-50 text-red-700'
                                                : 'bg-amber-50 text-amber-700'
                                            }`}>
                                            {file.status === 'ready' || file.status === 'vectorized'
                                                ? <CheckCircle2 className="w-3 h-3" />
                                                : (file.status === 'failed' || file.status === 'error')
                                                    ? <CircleDashed className="w-3 h-3 text-red-500" />
                                                    : <CircleDashed className="w-3 h-3 animate-spin" />
                                            }
                                            {file.status === 'ready' || file.status === 'vectorized'
                                                ? t('statusReadyFragment')
                                                : (file.status === 'failed' || file.status === 'error')
                                                    ? t('statusFailedFragment')
                                                    : t('statusIndexingFragment')
                                            }
                                        </span>
                                    </div>
                                    <div className="col-span-2 flex items-center min-w-0">
                                        <div className="flex-1 min-w-0">
                                            <FileGroupTags
                                                fileId={file.id}
                                                groups={groups}
                                                assignedGroups={file.groups?.map(g => g.id) || []}
                                                onGroupsChange={(groupIds) => handleFileGroupsChange(file.id, groupIds)}
                                                isAdmin={isAdmin}
                                            />
                                        </div>
                                        {isAdmin && (
                                            <button
                                                onClick={(e) => {
                                                    e.stopPropagation();
                                                    // FileGroupTags を開くためのカスタムイベントを発火
                                                    const event = new CustomEvent('openGroupSelector', { detail: { fileId: file.id } });
                                                    document.dispatchEvent(event);
                                                }}
                                                className="p-1 ml-1 text-slate-400 hover:text-blue-600 hover:bg-blue-50 rounded"
                                                title={t('addGroup')}
                                            >
                                                <FolderPlus className="w-4 h-4" />
                                            </button>
                                        )}
                                    </div>
                                    <div className="col-span-2 flex items-center justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
                                        {isSupportedForPreview(file) && (
                                            <button
                                                onClick={() => setPdfPreview({ fileId: file.id, fileName: file.name })}
                                                className="p-1.5 text-slate-400 hover:text-blue-600 hover:bg-blue-50 rounded"
                                                title={t('preview')}
                                            >
                                                <Eye className="w-4 h-4" />
                                            </button>
                                        )}
                                        <button
                                            onClick={() => fetchAndSetFiles()}
                                            className={`p-1.5 rounded ${isAutoRefreshEnabled
                                                ? 'text-green-600 hover:bg-green-50'
                                                : 'text-slate-400 hover:text-blue-600 hover:bg-blue-50'
                                                }`}
                                            title={isAutoRefreshEnabled ? t('autoRefresh') : t('refresh')}
                                        >
                                            <RefreshCw className={`w-4 h-4 ${isAutoRefreshEnabled ? 'animate-spin' : ''}`} />
                                        </button>
                                        {(file.status === 'failed' || file.status === 'error') && isAdmin && (
                                            <button
                                                onClick={() => handleRetryFile(file.id)}
                                                className="p-1.5 text-slate-400 hover:text-green-600 hover:bg-green-50 rounded"
                                                title={t('retry')}
                                            >
                                                <RotateCcw className="w-4 h-4" />
                                            </button>
                                        )}
                                        {isAdmin && (
                                            <button
                                                onClick={() => handleRemoveFile(file.id)}
                                                className="p-1.5 text-slate-400 hover:text-red-600 hover:bg-red-50 rounded"
                                                title={t('delete')}
                                            >
                                                <Trash2 className="w-4 h-4" />
                                            </button>
                                        )}
                                    </div>
                                </div>
                            ))
                        ) : (
                            <div className="h-full flex flex-col items-center justify-center p-8">
                                {isLoadingFiles ? (
                                    <div className="flex flex-col items-center gap-4">
                                        <div className="w-12 h-12 border-4 border-blue-600 border-t-transparent rounded-full animate-spin"></div>
                                        <p className="text-slate-600 font-medium">{t('loading')}</p>
                                    </div>
                                ) : (
                                    <div className="w-full max-w-2xl">
                                        <DragDropUpload
                                            onFilesSelected={handleFileUpload}
                                            isAdmin={isAdmin}
                                        />
                                    </div>
                                )}
                            </div>
                        )}
                    </div>

                    {/* Pagination */}
                    {totalPages > 1 && (
                        <div className="px-6 py-3 border-t border-slate-200 bg-slate-50 flex items-center justify-between shrink-0">
                            <span className="text-sm text-slate-500">
                                {t('showingRange')
                                    .replace('$1', `${(currentPage - 1) * pageSize + 1}`)
                                    .replace('$2', `${Math.min(currentPage * pageSize, filteredFiles.length)}`)
                                    .replace('$3', `${filteredFiles.length}`)}
                            </span>
                            <div className="flex items-center gap-2">
                                <button
                                    onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
                                    disabled={currentPage === 1}
                                    className="p-2 border border-slate-200 bg-white rounded hover:bg-slate-50 disabled:opacity-50 disabled:cursor-not-allowed"
                                >
                                    <ChevronLeft className="w-4 h-4" />
                                </button>
                                <span className="text-sm font-medium text-slate-700 min-w-[3rem] text-center">
                                    {currentPage} / {totalPages}
                                </span>
                                <button
                                    onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
                                    disabled={currentPage === totalPages}
                                    className="p-2 border border-slate-200 bg-white rounded hover:bg-slate-50 disabled:opacity-50 disabled:cursor-not-allowed"
                                >
                                    <ChevronRight className="w-4 h-4" />
                                </button>
                            </div>
                        </div>
                    )}
                </div>
            </div>

            {/* ドロワーとモーダル */}


            <IndexingModalWithMode
                isOpen={isIndexingModalOpen}
                onClose={() => {
                    setPendingFiles([])
                    setIsIndexingModalOpen(false)
                }}
                files={pendingFiles}
                embeddingModels={modelConfigs.filter(m => m.type === ModelType.EMBEDDING)}
                defaultEmbeddingId={settings.selectedEmbeddingId}
                onConfirm={handleConfirmIndexing}
            />

            {pdfPreview && (
                <PDFPreview
                    fileId={pdfPreview.fileId}
                    fileName={pdfPreview.fileName}
                    authToken={authToken}
                    onClose={() => setPdfPreview(null)}
                />
            )}

            {chunkDrawer && (
                <ChunkInfoDrawer
                    isOpen={chunkDrawer.isOpen}
                    onClose={() => setChunkDrawer(null)}
                    fileId={chunkDrawer.fileId}
                    fileName={chunkDrawer.fileName}
                    authToken={authToken}
                />
            )}

            <SettingsDrawer
                isOpen={isSettingsOpen}
                onClose={() => setIsSettingsOpen(false)}
                settings={settings}
                models={modelConfigs}
                onSettingsChange={handleUpdateSettings}
                onOpenSettings={() => onNavigate('settings')}
                mode="all"
                isAdmin={isAdmin}
            />
        </div>
    )
}
