import React, { useCallback, useEffect, useState, useMemo } 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 { ChunkInfoDrawer } from '../../components/ChunkInfoDrawer'
import {
    Search,
    Filter,
    Plus,
    FileText,
    Image as ImageIcon,
    FileType,
    CheckCircle2,
    CircleDashed,
    RefreshCw,
    Eye,
    Trash2,
    RotateCcw,
    Settings,
    MoreVertical
} from 'lucide-react'
import { motion, AnimatePresence } from 'framer-motion'
import { KB_ALLOWED_EXTENSIONS, IMAGE_MIME_TYPES, isExtensionAllowed, 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, modelConfigs = DEFAULT_MODELS, 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 [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())
    const [shouldOpenModal, setShouldOpenModal] = useState(false)

    // 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 = 12 // Adjusted for card grid
    const [chunkDrawer, setChunkDrawer] = useState<{ isOpen: boolean; fileId: string; fileName: string } | null>(null)

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

    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)
        } 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])

    useEffect(() => {
        if (shouldOpenModal && pendingFiles.length > 0) {
            setIsIndexingModalOpen(true);
            setShouldOpenModal(false);
        }
    }, [shouldOpenModal, pendingFiles.length]);

    const handleFileUpload = async (fileList: FileList) => {
        if (!authToken) {
            showWarning(t('loginRequired'))
            return
        }

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

        const filesArray = Array.from(fileList);
        for (const file of filesArray) {
            const extension = file.name.split('.').pop() || ''
            if (!isExtensionAllowed(extension, 'kb')) {
                errors.push(t('unsupportedFileType', file.name, extension))
                continue
            }
            if (file.size > MAX_FILE_SIZE) {
                errors.push(t('fileSizeLimitExceeded', file.name, formatBytes(file.size), 100))
                continue;
            }
            try {
                const rawFile = await readFile(file)
                rawFiles.push(rawFile)
            } catch (error) {
                errors.push(`${file.name} - ${t('readingFailed')}`);
            }
        }

        if (errors.length > 0) showError(`${t('uploadErrors')}:\n${errors.join('\n')}`);
        if (rawFiles.length === 0) return;

        setPendingFiles(rawFiles);
        setShouldOpenModal(true);
    }

    const handleConfirmIndexing = async (config: IndexingConfig) => {
        if (!authToken) return
        let hasSuccess = false

        for (const rawFile of pendingFiles) {
            try {
                await uploadService.uploadFileWithConfig(rawFile.file, config, authToken)
                hasSuccess = true
            } catch (error: any) {
                showError(`${t('uploadFailed')}: ${rawFile.name} - ${error.message}`)
            }
        }
        if (hasSuccess) await fetchAndSetFiles()
        setPendingFiles([])
        setIsIndexingModalOpen(false)
    }

    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: any) {
            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: any) {
            showError(`${t('clearFailed')}: ` + error.message)
        }
    }


    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]);

    useEffect(() => {
        let intervalId: NodeJS.Timeout | null = null;
        const hasIndexingFiles = files.some(file => ['pending', 'indexing', 'extracted', 'vectorized'].includes(file.status));

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

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

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

    if (isLoadingSettings) {
        return (
            <div className='flex items-center justify-center min-h-[400px] w-full'>
                <div className='text-blue-600 animate-spin rounded-full h-8 w-8 border-2 border-t-transparent border-blue-600'></div>
            </div>
        )
    }

    return (
        <div className='flex flex-col h-full w-full bg-transparent overflow-hidden'>
            <input
                type="file"
                ref={fileInputRef}
                onChange={(e) => {
                    if (e.target.files && e.target.files.length > 0) handleFileUpload(e.target.files)
                }}
                multiple
                className="hidden"
                accept={KB_ALLOWED_EXTENSIONS.map(ext => `.${ext}`).join(',') + ',' + IMAGE_MIME_TYPES.join(',')}
            />

            <GlobalDragDropOverlay onFilesSelected={handleFileUpload} isAdmin={isAdmin} />

            {/* Header Section */}
            <div className="px-8 pt-8 pb-6 flex items-start justify-between shrink-0">
                <div>
                    <h1 className="text-2xl font-bold text-slate-900 leading-tight">Knowledge Base</h1>
                    <p className="text-[15px] text-slate-500 mt-1">Manage your documents and data sources.</p>
                </div>
                <div className="flex items-center gap-3">
                    {isAdmin && (
                        <button
                            onClick={() => fileInputRef.current?.click()}
                            className="flex items-center gap-2 px-5 py-2.5 bg-blue-600 hover:bg-blue-700 text-white rounded-lg shadow-sm shadow-blue-100 transition-all font-semibold text-sm active:scale-95"
                        >
                            <Plus size={18} />
                            Add Document
                        </button>
                    )}
                </div>
            </div>

            {/* Filter Bar */}
            <div className="px-8 pb-6 flex items-center justify-between gap-4 shrink-0">
                <div className="flex items-center gap-3 flex-1">
                    <div className="relative max-w-xs w-full">
                        <Search className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" size={16} />
                        <input
                            type="text"
                            placeholder="Filter by name..."
                            value={filterName}
                            onChange={(e) => setFilterName(e.target.value)}
                            className="w-full h-9 pl-9 pr-4 bg-white border border-slate-200 rounded-lg text-sm transition-all focus:ring-1 focus:ring-blue-500 focus:border-blue-500 outline-none"
                        />
                    </div>
                    <select
                        value={filterGroup}
                        onChange={(e) => setFilterGroup(e.target.value)}
                        className="h-9 px-3 bg-white border border-slate-200 rounded-lg text-sm outline-none focus:ring-1 focus:ring-blue-500 min-w-[140px]"
                    >
                        <option value="all">All Groups</option>
                        {groups.map(g => <option key={g.id} value={g.id}>{g.name}</option>)}
                    </select>
                </div>
                <div className="flex items-center gap-3">
                    <button
                        onClick={() => fetchAndSetFiles()}
                        className="p-2 text-slate-400 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-all"
                        title="Refresh"
                    >
                        <RefreshCw size={18} className={isAutoRefreshEnabled ? 'animate-spin' : ''} />
                    </button>
                </div>
            </div>

            {/* Card Grid */}
            <div className="flex-1 overflow-y-auto px-8 pb-8">
                {isLoadingFiles ? (
                    <div className="flex flex-col items-center justify-center py-20 gap-4">
                        <div className="w-10 h-10 border-2 border-blue-600 border-t-transparent rounded-full animate-spin"></div>
                    </div>
                ) : paginatedFiles.length > 0 ? (
                    <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-6">
                        <AnimatePresence mode="popLayout">
                            {paginatedFiles.map((file) => (
                                <motion.div
                                    key={file.id}
                                    layout
                                    initial={{ opacity: 0, y: 10 }}
                                    animate={{ opacity: 1, y: 0 }}
                                    exit={{ opacity: 0, scale: 0.95 }}
                                    className="bg-white rounded-xl border border-slate-200/80 p-5 shadow-sm hover:shadow-md transition-all group relative overflow-hidden flex flex-col h-full"
                                >
                                    <div className="flex items-start justify-between mb-4">
                                        <div className="p-2.5 bg-blue-50 rounded-lg text-blue-600 shadow-sm border border-blue-100/30">
                                            {getFileIcon(file)}
                                        </div>
                                        <div className="flex items-center gap-1 opacity-100 md:opacity-0 group-hover:opacity-100 transition-opacity">
                                            {isFormatSupportedForPreview(file.name) && (
                                                <button onClick={() => setPdfPreview({ fileId: file.id, fileName: file.name })} className="p-1.5 text-slate-400 hover:text-blue-600 rounded-md">
                                                    <Eye size={16} />
                                                </button>
                                            )}
                                            {isAdmin && (
                                                <button onClick={() => handleRemoveFile(file.id)} className="p-1.5 text-slate-400 hover:text-red-500 rounded-md">
                                                    <Trash2 size={16} />
                                                </button>
                                            )}
                                        </div>
                                    </div>

                                    <div className="flex-1">
                                        <h3
                                            onClick={() => setChunkDrawer({ isOpen: true, fileId: file.id, fileName: file.name })}
                                            className="font-bold text-slate-900 text-[15px] mb-2 leading-snug cursor-pointer hover:text-blue-600 transition-colors line-clamp-2"
                                        >
                                            {file.name}
                                        </h3>
                                        <p className="text-[13px] text-slate-500 mb-4 line-clamp-3 min-h-[3em] leading-relaxed">
                                            {file.status === 'ready' || file.status === 'vectorized'
                                                ? `The ${file.name.split('.').pop()?.toUpperCase()} document has been processed and is ready for use in the Knowledge Base.`
                                                : `Processing... Currently in ${file.status} state. Results will be available shortly.`
                                            }
                                        </p>
                                    </div>

                                    <div className="mt-auto pt-4 border-t border-slate-50 flex items-center justify-between">
                                        <div className="text-[12px] font-medium text-slate-400 flex items-center gap-2">
                                            <span>{new Date().toLocaleDateString('ja-JP')}</span>
                                            <span className="w-1 h-1 bg-slate-200 rounded-full" />
                                            <span>{formatBytes(file.size)}</span>
                                        </div>
                                        <div className="flex items-center gap-2">
                                            <span className="px-2 py-0.5 bg-slate-100 text-slate-500 rounded text-[10px] font-bold tracking-wider uppercase">
                                                {file.name.split('.').pop()?.toUpperCase() || 'FILE'}
                                            </span>
                                            {file.status !== 'ready' && file.status !== 'vectorized' && (
                                                <CircleDashed size={14} className="text-blue-400 animate-spin" />
                                            )}
                                        </div>
                                    </div>
                                </motion.div>
                            ))}
                        </AnimatePresence>
                    </div>
                ) : (
                    <div className="max-w-4xl mx-auto w-full pt-12">
                        <DragDropUpload onFilesSelected={handleFileUpload} isAdmin={isAdmin} />
                    </div>
                )}
            </div>

            {/* Pagination */}
            {totalPages > 1 && (
                <div className="px-8 py-4 border-t border-slate-200/60 bg-white/50 backdrop-blur-md flex items-center justify-center gap-2 shrink-0">
                    <button
                        onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
                        disabled={currentPage === 1}
                        className="p-2 border border-slate-200 rounded-lg hover:bg-slate-50 disabled:opacity-30 transition-all font-medium text-slate-600"
                    >
                        Previous
                    </button>
                    <div className="px-3 py-2 text-sm font-semibold text-slate-700">
                        {currentPage} of {totalPages}
                    </div>
                    <button
                        onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
                        disabled={currentPage === totalPages}
                        className="p-2 border border-slate-200 rounded-lg hover:bg-slate-50 disabled:opacity-30 transition-all font-medium text-slate-600"
                    >
                        Next
                    </button>
                </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}
                />
            )}

        </div>
    )
}
