import React, { useCallback, useEffect, useState, useRef } from 'react'
import ChatInterface from '../../components/ChatInterface'
import IndexingModalWithMode from '../../components/IndexingModalWithMode'
import { GroupManager } from '../../components/GroupManager'
import { GroupSelector } from '../../components/GroupSelector'
import { SearchHistoryList } from '../../components/SearchHistoryList'
import { HistoryDrawer } from '../../components/HistoryDrawer'
import { GroupSelectionDrawer } from '../../components/GroupSelectionDrawer'
import { PDFPreview } from '../../components/PDFPreview'
import { SourcePreviewDrawer } from '../../components/SourcePreviewDrawer'
import { ChatSource } from '../../services/chatService'
import {
    AppSettings,
    DEFAULT_MODELS,
    DEFAULT_SETTINGS,
    IndexingConfig,
    KnowledgeFile,
    ModelConfig,
    ModelType,
    RawFile,
    KnowledgeGroup,
} from '../../types'
import { readFile, formatBytes } from '../../utils/fileUtils'
import { isFormatSupportedForPreview } from '../../constants/fileSupport'
import { Key, LogOut, Menu, Users, X, Folder, History, Plus, Sparkles, Settings } from 'lucide-react'
import { useLanguage } from '../../contexts/LanguageContext'
import { useToast } from '../../contexts/ToastContext'
import { modelConfigService } from '../../services/modelConfigService'
import { userSettingService } from '../../services/userSettingService'
import { uploadService } from '../../services/uploadService'
import { knowledgeBaseService } from '../../services/knowledgeBaseService'
import { knowledgeGroupService } from '../../services/knowledgeGroupService'
import { searchHistoryService } from '../../services/searchHistoryService'
import { userService } from '../../services/userService'

interface ChatViewProps {
    authToken: string;
    onLogout: () => void;
    modelConfigs?: ModelConfig[]; // Optional to allow backward compat while refactoring
    onNavigate: (view: any) => void;
    initialChatContext?: { selectedGroups?: string[], selectedFiles?: string[] } | null;
    onClearContext?: () => void;
    isAdmin?: boolean;
}

export const ChatView: React.FC<ChatViewProps> = ({
    authToken,
    onLogout,
    modelConfigs = DEFAULT_MODELS,
    onNavigate,
    initialChatContext,
    onClearContext,
    isAdmin = false
}) => {
    const { showError, showWarning } = useToast()

    const [files, setFiles] = useState<KnowledgeFile[]>([])
    const [groups, setGroups] = useState<KnowledgeGroup[]>([])
    const [settings, setSettings] = useState<AppSettings>(DEFAULT_SETTINGS)
    const [isLoadingSettings, setIsLoadingSettings] = useState(true)

    const [isGroupManagerOpen, setIsGroupManagerOpen] = useState(false)
    const [isHistoryOpen, setIsHistoryOpen] = useState(false)
    const [isGroupSelectionOpen, setIsGroupSelectionOpen] = useState(false) // New state
    const [currentHistoryId, setCurrentHistoryId] = useState<string | undefined>()
    const [historyMessages, setHistoryMessages] = useState<any[] | null>(null)
    const [selectedGroups, setSelectedGroups] = useState<string[]>([])
    const [selectedFiles, setSelectedFiles] = useState<string[]>([])
    const [pdfPreview, setPdfPreview] = useState<{ fileId: string; fileName: string } | null>(null)
    const [previewSource, setPreviewSource] = useState<ChatSource | null>(null)

    const [isIndexingModalOpen, setIsIndexingModalOpen] = useState(false)
    const [pendingFiles, setPendingFiles] = useState<RawFile[]>([])

    // Modals state removed as they are moved to Settings
    const [isLanguageLoading, setIsLanguageLoading] = useState(false)

    const { t, language, setLanguage } = useLanguage()
    const fileInputRef = useRef<HTMLInputElement>(null)


    const handleNewChat = () => {
        const currentLanguage = language
        localStorage.removeItem('chatHistory')
        localStorage.removeItem('chatMessages')
        localStorage.removeItem('chatSources')
        localStorage.setItem('userLanguage', currentLanguage)
        setCurrentHistoryId(undefined)
        setHistoryMessages(null)
        window.location.reload()
    }

    // Function to fetch user settings from backend
    const fetchAndSetSettings = useCallback(async () => {
        if (!authToken) return
        try {
            const [personalSettings, tenantSettings] = await Promise.all([
                userSettingService.getPersonal(authToken).catch(() => null),
                userSettingService.get(authToken).catch(() => ({} as Partial<AppSettings>))
            ]);

            const appSettings: AppSettings = {
                ...DEFAULT_SETTINGS,
                ...tenantSettings,
                language: personalSettings?.language || tenantSettings?.language || DEFAULT_SETTINGS.language,
            };
            setSettings(appSettings)
        } catch (error) {
            console.error('Failed to fetch settings:', error)
            setSettings(DEFAULT_SETTINGS)
        } finally {
            setIsLoadingSettings(false)
        }
    }, [authToken])

    const fetchAndSetFiles = useCallback(async () => {
        if (!authToken) return
        try {
            const data = await knowledgeBaseService.getAll(authToken)
            setFiles(data.items)
        } catch (error) {
            console.error('Failed to fetch files:', error)
        }
    }, [authToken])

    // Function to fetch groups from backend
    const fetchAndSetGroups = useCallback(async () => {
        if (!authToken) return
        try {
            const remoteGroups = await knowledgeGroupService.getGroups()
            setGroups(remoteGroups)

            // Filter out selected groups that no longer exist
            setSelectedGroups(prev => {
                const validGroupIds = new Set(remoteGroups.map(g => g.id))
                return prev.filter(id => validGroupIds.has(id))
            })
        } catch (error) {
            console.error('Failed to fetch groups:', error)
        }
    }, [authToken])

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

    // Handle Initial Context
    useEffect(() => {
        if (initialChatContext) {
            if (initialChatContext.selectedGroups) {
                setSelectedGroups(initialChatContext.selectedGroups)
            }
            if (initialChatContext.selectedFiles) {
                setSelectedFiles(initialChatContext.selectedFiles)
            }
        }
    }, [initialChatContext])

    // Load chat history from localStorage on mount
    useEffect(() => {
        const savedHistory = localStorage.getItem('chatMessages');
        if (savedHistory) {
            try {
                const parsedHistory = JSON.parse(savedHistory);
                if (Array.isArray(parsedHistory) && parsedHistory.length > 0) {
                    setHistoryMessages(parsedHistory);
                }
            } catch (error) {
                console.error('Failed to parse saved chat history:', error);
            }
        }
    }, []);

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

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

        for (let i = 0; i < fileList.length; i++) {
            const file = fileList[i]
            if (file.size > MAX_FILE_SIZE) {
                errors.push(t('fileSizeLimitExceeded').replace('$1', file.name).replace('$2', formatBytes(file.size)).replace('$3', MAX_SIZE_MB.toString()))
                continue
            }

            const allowedTypes = [
                'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
                'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet',
                'application/vnd.oasis.opendocument.presentation', 'application/vnd.oasis.opendocument.graphics',
                'text/plain', 'text/markdown', 'text/html', 'text/csv', 'text/xml', 'application/xml', 'application/json',
                'text/x-python', 'text/x-java', 'text/x-c', 'text/x-c++', 'text/javascript', 'text/typescript',
                'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/tiff', 'image/bmp', 'image/svg+xml',
                'application/zip', 'application/x-tar', 'application/gzip', 'application/x-7z-compressed',
                'application/rtf', 'application/epub+zip', 'application/x-mobipocket-ebook',
            ]

            const ext = file.name.toLowerCase().split('.').pop()
            const allowedExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md', 'html', 'csv', 'rtf', 'odt', 'ods', 'odp', 'json', 'xml']

            const isAllowed = allowedTypes.includes(file.type) ||
                file.type.startsWith('text/') ||
                file.type.startsWith('application/vnd.') ||
                file.type.startsWith('application/x-') ||
                file.type === '' ||
                allowedExtensions.includes(ext || '')

            if (!isAllowed) {
                errors.push(t('unsupportedFileType').replace('$1', file.name).replace('$2', file.type || 'unknown'))
                continue
            }

            try {
                const rawFile = await readFile(file)
                rawFiles.push(rawFile)
            } catch (error) {
                console.error(`Error reading file ${file.name}:`, error)
                errors.push(t('readFailed').replace('$1', file.name))
            }
        }

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

        if (rawFiles.length === 0) return

        if (errors.length > 0 && rawFiles.length > 0) {
            showWarning(t('uploadWarning').replace('$1', rawFiles.length.toString()).replace('$2', errors.length.toString()))
        }

        setPendingFiles(rawFiles);
        setIsIndexingModalOpen(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) {
                console.error(`Error uploading file ${rawFile.name}:`, error)
                showError(t('uploadFailed').replace('$1', rawFile.name).replace('$2', error.message))
            }
        }
        if (hasSuccess) {
            await fetchAndSetFiles()
        }
        setPendingFiles([])
        setIsIndexingModalOpen(false)
    }

    const handleCancelIndexing = () => {
        setPendingFiles([])
        setIsIndexingModalOpen(false)
    }

    const handleGroupsChange = (newGroups: KnowledgeGroup[]) => {
        setGroups(newGroups)
    }

    const handleSelectHistory = async (historyId: string) => {
        try {
            const historyDetail = await searchHistoryService.getHistoryDetail(historyId)
            setCurrentHistoryId(historyId)
            setIsHistoryOpen(false)
            setHistoryMessages(historyDetail.messages)
        } catch (error) {
            console.error('Failed to load history detail:', error)
            showError(t('loadHistoryFailed'))
        }
    }

    const handleShowHistory = () => {
        setIsHistoryOpen(true)
    }

    const handleInputFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (e.target.files && e.target.files.length > 0) {
            handleFileUpload(e.target.files)
        }
        if (fileInputRef.current) {
            fileInputRef.current.value = ''
        }
    }

    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>
                <p className='ml-4 text-slate-700'>{t('loadingUserData')}</p>
            </div>
        )
    }

    return (
        <div className='flex h-full w-full bg-transparent overflow-hidden relative'>

            <input
                type="file"
                ref={fileInputRef}
                onChange={handleInputFileChange}
                multiple
                className="hidden"
                accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.md,.html,.csv,.rtf,.odt,.ods,.odp,.json,.js,.jsx,.ts,.tsx,.css,.xml,image/*"
            />
            {/* Main Content */}
            <div className='flex-1 flex flex-col h-full w-full relative overflow-hidden'>
                {/* Header */}
                <div className="px-8 pt-8 pb-4 flex items-start justify-between shrink-0 z-20">
                    <div>
                        <h1 className="text-2xl font-bold text-slate-900 leading-tight">
                            {t('chatTitle')}
                        </h1>
                        <p className="text-[15px] text-slate-500 mt-1">{t('chatDesc')}</p>
                    </div>

                    <div className='flex items-center gap-3 flex-shrink-0'>
                        {/* 历史记录按钮 */}
                        <button
                            onClick={handleShowHistory}
                            className="flex items-center gap-2 px-4 py-2 bg-white border border-slate-200 text-slate-700 hover:text-blue-600 hover:bg-slate-50 rounded-lg font-semibold text-sm transition-all shadow-sm"
                        >
                            <History size={18} />
                            {t('viewHistory')}
                        </button>

                        {/* New chat button */}
                        <button
                            onClick={handleNewChat}
                            className="flex items-center gap-2 px-5 py-2 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} />
                            {t('newChat')}
                        </button>
                    </div>
                </div>

                <div className='flex-1 overflow-hidden'>
                    <ChatInterface
                        files={files}
                        settings={settings}
                        models={modelConfigs}
                        groups={groups}
                        selectedGroups={selectedGroups}
                        onGroupSelectionChange={setSelectedGroups}
                        onOpenGroupSelection={() => setIsGroupSelectionOpen(true)} // Pass handler
                        selectedFiles={selectedFiles}
                        onClearFileSelection={() => setSelectedFiles([])}
                        onMobileUploadClick={() => {
                            fileInputRef.current?.click()
                        }}
                        currentHistoryId={currentHistoryId}
                        historyMessages={historyMessages}
                        onHistoryMessagesLoaded={() => setHistoryMessages(null)}
                        onHistoryIdCreated={setCurrentHistoryId}
                        onPreviewSource={setPreviewSource}
                        onOpenFile={(source) => {
                            if (source.fileId) {
                                if (isFormatSupportedForPreview(source.fileName)) {
                                    setPdfPreview({ fileId: source.fileId, fileName: source.fileName });
                                } else {
                                    showWarning(t('previewNotSupported'));
                                }
                            }
                        }}
                    />
                </div>
            </div>

            {/* Modals */}

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

            {/* Group Selection Drawer */}
            <GroupSelectionDrawer
                isOpen={isGroupSelectionOpen}
                onClose={() => setIsGroupSelectionOpen(false)}
                groups={groups}
                selectedGroups={selectedGroups}
                onSelectionChange={setSelectedGroups}
            />

            {/* Knowledge base enhancement features modal (Legacy) */}
            {isGroupManagerOpen && (
                <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
                    <div className="bg-white rounded-lg p-6 w-full max-w-2xl max-h-[80vh] overflow-y-auto">
                        <div className="flex items-center justify-between mb-4">
                            <h2 className="text-xl font-semibold">{t('notebooks')}</h2>
                            <button
                                onClick={() => setIsGroupManagerOpen(false)}
                                className="text-gray-400 hover:text-gray-600"
                            >
                                <X size={24} />
                            </button>
                        </div>
                        <GroupManager
                            groups={groups}
                            onGroupsChange={handleGroupsChange}
                        />
                    </div>
                </div>
            )}

            <HistoryDrawer
                isOpen={isHistoryOpen}
                onClose={() => setIsHistoryOpen(false)}
                groups={groups}
                onSelectHistory={handleSelectHistory}
            />

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

            <SourcePreviewDrawer
                isOpen={!!previewSource}
                onClose={() => setPreviewSource(null)}
                source={previewSource}
                onOpenFile={(source) => {
                    if (source.fileId) {
                        if (isFormatSupportedForPreview(source.fileName)) {
                            setPdfPreview({ fileId: source.fileId, fileName: source.fileName });
                        } else {
                            showWarning(t('previewNotSupported'));
                        }
                    }
                }}
            />

        </div>
    )
}
