import React, { useState, useEffect } from 'react';
import { X, FolderInput, ArrowRight, Info, Layers, Clock, Upload, Calendar } from 'lucide-react';
import { isExtensionAllowed } from '../constants/fileSupport';
import { useLanguage } from '../contexts/LanguageContext';
import { ModelConfig, ModelType, IndexingConfig, KnowledgeGroup } from '../types';
import { modelConfigService } from '../services/modelConfigService';
import { knowledgeGroupService } from '../services/knowledgeGroupService';
import { apiClient } from '../services/apiClient';
import { useToast } from '../contexts/ToastContext';
import IndexingModalWithMode from './IndexingModalWithMode';

interface ImportFolderDrawerProps {
    isOpen: boolean;
    onClose: () => void;
    authToken: string;
    initialGroupId?: string;
    initialGroupName?: string;
    onImportSuccess?: () => void;
}

interface FileWithPath {
    file: File;
    relativePath: string;
}

type ImportMode = 'immediate' | 'scheduled';

export const ImportFolderDrawer: React.FC<ImportFolderDrawerProps> = ({
    isOpen,
    onClose,
    authToken,
    initialGroupId,
    initialGroupName,
    onImportSuccess,
}) => {
    const { t } = useLanguage();
    const { showError, showSuccess } = useToast();

    // Tab
    const [importMode, setImportMode] = useState<ImportMode>('immediate');

    // Immediate mode state
    const [localFiles, setLocalFiles] = useState<FileWithPath[]>([]);
    const [folderName, setFolderName] = useState('');
    const [targetName, setTargetName] = useState('');
    const [useHierarchy, setUseHierarchy] = useState(false);
    const fileInputRef = React.useRef<HTMLInputElement>(null);
    const [isIndexingConfigOpen, setIsIndexingConfigOpen] = useState(false);
    const [models, setModels] = useState<ModelConfig[]>([]);

    // Scheduled mode state
    const [serverPath, setServerPath] = useState('');
    const [scheduledTime, setScheduledTime] = useState(() => {
        // Default to 30 min from now
        const d = new Date();
        d.setMinutes(d.getMinutes() + 30);
        d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
        return d.toISOString().slice(0, 16); // "YYYY-MM-DDTHH:mm"
    });
    const [schedTargetName, setSchedTargetName] = useState('');
    const [schedUseHierarchy, setSchedUseHierarchy] = useState(false);

    const [isLoading, setIsLoading] = useState(false);
    const [allGroups, setAllGroups] = useState<KnowledgeGroup[]>([]);
    const [parentGroupId, setParentGroupId] = useState<string>('');
    const [schedParentGroupId, setSchedParentGroupId] = useState<string>('');

    useEffect(() => {
        if (isOpen) {
            setLocalFiles([]);
            setFolderName('');
            setTargetName(initialGroupName || '');
            setUseHierarchy(false);
            setIsIndexingConfigOpen(false);
            setImportMode('immediate');
            setServerPath('');
            setSchedTargetName(initialGroupName || '');
            setSchedUseHierarchy(false);
            setParentGroupId('');
            setSchedParentGroupId('');

            // Default scheduled time = 30min from now
            const d = new Date();
            d.setMinutes(d.getMinutes() + 30);
            d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
            setScheduledTime(d.toISOString().slice(0, 16));

            modelConfigService.getAll(authToken).then(res => {
                setModels(res.filter(m => m.type === ModelType.EMBEDDING));
            });

            knowledgeGroupService.getGroups().then(groups => {
                const flat: any[] = [];
                function walk(items: any[], depth = 0) {
                    for (const g of items) {
                        flat.push({ ...g, d: depth });
                        if (g.children?.length) walk(g.children, depth + 1);
                    }
                }
                walk(groups);
                setAllGroups(flat);
            });
        }
    }, [isOpen, authToken, initialGroupName]);

    // ---- Immediate mode handlers ----
    const handleLocalFolderChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (e.target.files && e.target.files.length > 0) {
            const allFiles = Array.from(e.target.files);
            const files: FileWithPath[] = allFiles
                .filter(file => {
                    const ext = file.name.split('.').pop() || '';
                    return isExtensionAllowed(ext, 'group');
                })
                .map(file => ({
                    file,
                    relativePath: file.webkitRelativePath || file.name,
                }));

            if (files.length === 0 && allFiles.length > 0) {
                showError(t('noFilesFound'));
                return;
            }
            setLocalFiles(files);

            const firstPath = allFiles[0].webkitRelativePath;
            if (firstPath) {
                const parts = firstPath.split('/');
                if (parts.length > 0) {
                    const name = parts[0];
                    setFolderName(name);
                    if (!initialGroupId && !targetName) setTargetName(name);
                }
            }
        }
    };

    const handleImmediateNext = () => {
        if (localFiles.length === 0) {
            showError(t('clickToSelectFolder'));
            return;
        }
        if (!initialGroupId && !targetName) {
            showError(t('fillTargetName'));
            return;
        }
        setIsIndexingConfigOpen(true);
    };

    const handleConfirmConfig = async (config: IndexingConfig) => {
        setIsLoading(true);
        try {
            const { uploadService } = await import('../services/uploadService');

            if (useHierarchy) {
                // Step 1: Determine root group
                let rootGroupId = initialGroupId ?? null;
                if (!rootGroupId) {
                    const newGroup = await knowledgeGroupService.createGroup({
                        name: targetName,
                        description: t('importedFromLocalFolder').replace('$1', folderName),
                        parentId: parentGroupId || null,
                    });
                    rootGroupId = newGroup.id;
                }

                // Step 2: Collect all unique directory paths
                const dirSet = new Set<string>();
                for (const { relativePath } of localFiles) {
                    const parts = relativePath.split('/');
                    const dirParts = initialGroupId
                        ? parts.slice(1, parts.length - 1)
                        : parts.slice(0, parts.length - 1);
                    for (let i = 1; i <= dirParts.length; i++) {
                        dirSet.add(dirParts.slice(0, i).join('/'));
                    }
                }

                // Step 3: Sort by depth, create groups sequentially
                const sortedDirs = Array.from(dirSet).sort((a, b) =>
                    a.split('/').length - b.split('/').length
                );
                const dirToGroupId = new Map<string, string>();
                dirToGroupId.set(initialGroupId ? '' : folderName, rootGroupId);

                for (const dirPath of sortedDirs) {
                    if (!dirPath || dirToGroupId.has(dirPath)) continue;
                    const segments = dirPath.split('/');
                    const segName = segments[segments.length - 1];
                    const parentPath = segments.slice(0, segments.length - 1).join('/');
                    const parentId = dirToGroupId.get(parentPath) ?? rootGroupId;
                    const newGroup = await knowledgeGroupService.createGroup({ name: segName, parentId });
                    dirToGroupId.set(dirPath, newGroup.id);
                }

                // Step 4: Upload files in parallel batches
                const BATCH_SIZE = 3;
                for (let i = 0; i < localFiles.length; i += BATCH_SIZE) {
                    const batch = localFiles.slice(i, i + BATCH_SIZE);
                    await Promise.all(batch.map(async ({ file, relativePath }) => {
                        try {
                            const parts = relativePath.split('/');
                            const dirParts = initialGroupId
                                ? parts.slice(1, parts.length - 1)
                                : parts.slice(0, parts.length - 1);
                            const fileDirPath = dirParts.join('/');
                            const targetGroupId = dirToGroupId.get(fileDirPath) ?? rootGroupId!;
                            const uploadedKb = await uploadService.uploadFileWithConfig(file, config, authToken);
                            await knowledgeGroupService.addFileToGroups(uploadedKb.id, [targetGroupId]);
                        } catch (err) {
                            console.error(`Failed to upload ${file.name}:`, err);
                        }
                    }));
                }
            } else {
                // Single-group mode
                let groupId = initialGroupId ?? null;
                if (!groupId) {
                    const newGroup = await knowledgeGroupService.createGroup({
                        name: targetName,
                        description: t('importedFromLocalFolder').replace('$1', folderName),
                    });
                    groupId = newGroup.id;
                }
                const BATCH_SIZE = 3;
                for (let i = 0; i < localFiles.length; i += BATCH_SIZE) {
                    const batch = localFiles.slice(i, i + BATCH_SIZE);
                    await Promise.all(batch.map(async ({ file }) => {
                        try {
                            const uploadedKb = await uploadService.uploadFileWithConfig(file, config, authToken);
                            if (groupId) await knowledgeGroupService.addFileToGroups(uploadedKb.id, [groupId]);
                        } catch (err) {
                            console.error(`Failed to upload ${file.name}:`, err);
                        }
                    }));
                }
            }

            showSuccess(t('importComplete'));
            onImportSuccess?.();
            onClose();
        } catch (error: any) {
            showError(t('submitFailed', error.message));
        } finally {
            setIsLoading(false);
            setIsIndexingConfigOpen(false);
        }
    };

    // ---- Scheduled mode handler ----
    const handleScheduledSubmit = async () => {
        if (!serverPath.trim()) {
            showError(t('fillServerPath'));
            return;
        }
        if (!initialGroupId && !schedTargetName.trim()) {
            showError(t('fillTargetName'));
            return;
        }

        const scheduledAt = new Date(scheduledTime);
        if (isNaN(scheduledAt.getTime())) {
            showError(t('invalidDateTime' as any));
            return;
        }

        setIsLoading(true);
        try {
            let finalGroupId = initialGroupId || undefined;
            if (!finalGroupId && schedTargetName.trim()) {
                const newGroup = await knowledgeGroupService.createGroup({
                    name: schedTargetName.trim(),
                    description: t('importedFromLocalFolder').replace('$1', schedTargetName.trim()),
                    parentId: schedParentGroupId || null,
                });
                finalGroupId = newGroup.id;
            }

            const defaultModel = models[0];
            await apiClient.post('/import-tasks', {
                sourcePath: serverPath.trim(),
                targetGroupId: finalGroupId,
                targetGroupName: undefined,
                embeddingModelId: defaultModel?.id,
                scheduledAt: scheduledAt.toISOString(),
                chunkSize: 500,
                chunkOverlap: 50,
                mode: 'fast',
                useHierarchy: schedUseHierarchy,
            });

            showSuccess(t('scheduleTaskCreated'));
            onImportSuccess?.();
            onClose();
        } catch (error: any) {
            showError(t('submitFailed', error.message));
        } finally {
            setIsLoading(false);
        }
    };

    if (!isOpen) return null;

    return (
        <>
            <div className="fixed inset-0 z-50 flex justify-end">
                <div className="absolute inset-0 bg-black/20 backdrop-blur-sm transition-opacity" onClick={onClose} />

                <div className="relative w-full max-w-md bg-white shadow-2xl flex flex-col h-full animate-in slide-in-from-right duration-300">
                    {/* Header */}
                    <div className="px-6 py-4 border-b border-slate-100 flex items-center justify-between shrink-0 bg-white">
                        <h2 className="text-lg font-bold text-slate-800 flex items-center gap-2">
                            <FolderInput className="w-5 h-5 text-blue-600" />
                            {t('importFolderTitle')}
                        </h2>
                        <button onClick={onClose} className="p-2 -mr-2 text-slate-400 hover:text-slate-600 hover:bg-slate-50 rounded-full transition-colors">
                            <X size={20} />
                        </button>
                    </div>

                    {/* Mode Tabs */}
                    <div className="flex border-b border-slate-100 shrink-0">
                        <button
                            onClick={() => setImportMode('immediate')}
                            className={`flex-1 flex items-center justify-center gap-2 py-3 text-sm font-semibold transition-colors border-b-2 ${importMode === 'immediate'
                                ? 'border-blue-600 text-blue-600 bg-blue-50/40'
                                : 'border-transparent text-slate-500 hover:text-slate-700'
                                }`}
                        >
                            <Upload size={15} />
                            {t('importImmediate')}
                        </button>
                        <button
                            onClick={() => setImportMode('scheduled')}
                            className={`flex-1 flex items-center justify-center gap-2 py-3 text-sm font-semibold transition-colors border-b-2 ${importMode === 'scheduled'
                                ? 'border-blue-600 text-blue-600 bg-blue-50/40'
                                : 'border-transparent text-slate-500 hover:text-slate-700'
                                }`}
                        >
                            <Clock size={15} />
                            {t('importScheduled')}
                        </button>
                    </div>

                    {/* Body */}
                    <div className="flex-1 overflow-y-auto p-6 space-y-5">
                        {importMode === 'immediate' ? (
                            <>
                                {/* Immediate: folder picker */}
                                <div
                                    onClick={() => fileInputRef.current?.click()}
                                    className="border-2 border-dashed border-slate-200 rounded-xl p-8 flex flex-col items-center justify-center gap-3 cursor-pointer hover:border-blue-400 hover:bg-blue-50 transition-all group"
                                >
                                    <div className="w-12 h-12 bg-slate-50 text-slate-400 rounded-full flex items-center justify-center group-hover:bg-blue-100 group-hover:text-blue-600 transition-colors">
                                        <FolderInput size={24} />
                                    </div>
                                    <div className="text-center">
                                        <p className="text-sm font-medium text-slate-700">
                                            {localFiles.length > 0
                                                ? t('selectedFilesCount').replace('$1', localFiles.length.toString())
                                                : t('clickToSelectFolder')}
                                        </p>
                                        <p className="text-xs text-slate-400 mt-1">
                                            {localFiles.length > 0 ? folderName : t('selectFolderTip')}
                                        </p>
                                    </div>
                                    <input
                                        type="file"
                                        ref={fileInputRef}
                                        onChange={handleLocalFolderChange}
                                        className="hidden"
                                        multiple
                                        // @ts-ignore
                                        webkitdirectory=""
                                        directory=""
                                    />
                                </div>

                                {/* Target group */}
                                <div className="space-y-1.5">
                                    <label className="text-sm font-medium text-slate-700">{t('lblTargetGroup')}</label>
                                    <input
                                        type="text"
                                        value={targetName}
                                        onChange={e => setTargetName(e.target.value)}
                                        disabled={!!initialGroupId}
                                        placeholder={t('placeholderNewGroup')}
                                        className={`w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none ${initialGroupId ? 'bg-slate-50 text-slate-500' : ''}`}
                                    />
                                    {initialGroupId && <p className="text-xs text-slate-400">{t('importToCurrentGroup')}</p>}
                                </div>
                                {!initialGroupId && (
                                    <div className="space-y-1.5">
                                        <label className="text-sm font-medium text-slate-700">{t('parentCategory') || 'Parent Category'}</label>
                                        <select
                                            value={parentGroupId}
                                            onChange={e => setParentGroupId(e.target.value)}
                                            className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none"
                                        >
                                            <option value="">{t('allGroups' as any) || '-- Root --'}</option>
                                            {allGroups.map((g: any) => (
                                                <option key={g.id} value={g.id}>
                                                    {'\u00A0'.repeat(g.d * 4)}{g.name}
                                                </option>
                                            ))}
                                        </select>
                                    </div>
                                )}

                                {/* Hierarchy toggle */}
                                <HierarchyToggle value={useHierarchy} onChange={setUseHierarchy} t={t} />
                            </>
                        ) : (
                            <>
                                {/* Scheduled: server path */}
                                <div className="bg-amber-50 border border-amber-100 rounded-lg p-3 text-sm text-amber-800 flex items-start gap-2">
                                    <Info className="w-4 h-4 mt-0.5 shrink-0" />
                                    <p className="text-xs">{t('scheduledImportTip')}</p>
                                </div>

                                <div className="space-y-1.5">
                                    <label className="text-sm font-medium text-slate-700">{t('lblServerPath')}</label>
                                    <input
                                        type="text"
                                        value={serverPath}
                                        onChange={e => setServerPath(e.target.value)}
                                        placeholder={t('placeholderServerPath')}
                                        className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none font-mono"
                                    />
                                </div>

                                {/* Target group */}
                                <div className="space-y-1.5">
                                    <label className="text-sm font-medium text-slate-700">{t('lblTargetGroup')}</label>
                                    <input
                                        type="text"
                                        value={schedTargetName}
                                        onChange={e => setSchedTargetName(e.target.value)}
                                        disabled={!!initialGroupId}
                                        placeholder={t('placeholderNewGroup')}
                                        className={`w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none ${initialGroupId ? 'bg-slate-50 text-slate-500' : ''}`}
                                    />
                                    {initialGroupId && <p className="text-xs text-slate-400">{t('importToCurrentGroup')}</p>}
                                </div>
                                {!initialGroupId && (
                                    <div className="space-y-1.5">
                                        <label className="text-sm font-medium text-slate-700">{t('parentCategory') || 'Parent Category'}</label>
                                        <select
                                            value={schedParentGroupId}
                                            onChange={e => setSchedParentGroupId(e.target.value)}
                                            className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none"
                                        >
                                            <option value="">{t('allGroups' as any) || '-- Root --'}</option>
                                            {allGroups.map((g: any) => (
                                                <option key={g.id} value={g.id}>
                                                    {'\u00A0'.repeat(g.d * 4)}{g.name}
                                                </option>
                                            ))}
                                        </select>
                                    </div>
                                )}

                                {/* Scheduled datetime */}
                                <div className="space-y-1.5">
                                    <label className="text-sm font-medium text-slate-700 flex items-center gap-1.5">
                                        <Calendar size={14} className="text-blue-500" />
                                        {t('lblScheduledTime')}
                                    </label>
                                    <input
                                        type="datetime-local"
                                        value={scheduledTime}
                                        onChange={e => setScheduledTime(e.target.value)}
                                        className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none"
                                    />
                                    <p className="text-xs text-slate-400">{t('scheduledTimeHint')}</p>
                                </div>

                                {/* Hierarchy toggle */}
                                <HierarchyToggle value={schedUseHierarchy} onChange={setSchedUseHierarchy} t={t} />
                            </>
                        )}
                    </div>

                    {/* Footer */}
                    <div className="p-6 border-t border-slate-100 shrink-0 flex gap-3 bg-slate-50">
                        <button
                            onClick={onClose}
                            className="flex-1 px-4 py-2 text-sm font-medium text-slate-600 hover:bg-slate-200 rounded-lg transition-colors"
                        >
                            {t('cancel')}
                        </button>
                        {importMode === 'immediate' ? (
                            <button
                                onClick={handleImmediateNext}
                                className="flex-1 px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow-sm flex justify-center items-center gap-2 transition-all"
                                disabled={isLoading}
                            >
                                <span>{isLoading ? t('uploading') : t('nextStep')}</span>
                                <ArrowRight size={16} />
                            </button>
                        ) : (
                            <button
                                onClick={handleScheduledSubmit}
                                className="flex-1 px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow-sm flex justify-center items-center gap-2 transition-all"
                                disabled={isLoading}
                            >
                                <Clock size={16} />
                                <span>{isLoading ? t('uploading') : t('scheduleImport')}</span>
                            </button>
                        )}
                    </div>
                </div>
            </div>

            {/* Indexing Config Modal (immediate mode only) */}
            <IndexingModalWithMode
                isOpen={isIndexingConfigOpen}
                onClose={() => setIsIndexingConfigOpen(false)}
                files={[]}
                embeddingModels={models}
                defaultEmbeddingId={models.length > 0 ? models[0].id : ''}
                onConfirm={handleConfirmConfig}
                isReconfiguring={false}
            />
        </>
    );
};

/** Reusable hierarchy toggle */
const HierarchyToggle: React.FC<{
    value: boolean;
    onChange: (v: boolean) => void;
    t: (key: string) => string;
}> = ({ value, onChange, t }) => (
    <label className="flex items-center gap-3 cursor-pointer select-none">
        <div className="relative">
            <input
                type="checkbox"
                checked={value}
                onChange={e => onChange(e.target.checked)}
                className="sr-only"
            />
            <div className={`w-10 h-5 rounded-full transition-colors ${value ? 'bg-blue-600' : 'bg-slate-200'}`} />
            <div className={`absolute top-0.5 left-0.5 w-4 h-4 rounded-full bg-white shadow transition-transform ${value ? 'translate-x-5' : ''}`} />
        </div>
        <div>
            <p className="text-sm font-medium text-slate-700 flex items-center gap-1.5">
                <Layers size={14} className="text-blue-500" />
                {t('useHierarchyImport')}
            </p>
            <p className="text-xs text-slate-400 mt-0.5">{t('useHierarchyImportDesc')}</p>
        </div>
    </label>
);
