import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Save, RotateCcw } from 'lucide-react';
import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
import { Button } from '@/components/ui/button';
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { useToast } from '@/components/ui/use-toast';
import type { FlowNode, FlowNodeData, FlowEdge } from '../types';
import type { WorkflowNodeDefinition, JSONSchema } from '../nodes/types';
import { isConfigurableNode } from '../nodes/types';
import { convertJsonSchemaToZod, extractDataSourceTypes } from '../utils/schemaConverter';
import { loadDataSource, DataSourceType, type DataSourceOption } from '../utils/dataSourceLoader';
import { convertObjectToUUID, convertObjectToDisplayName } from '@/utils/workflow/variableConversion';
import VariableInput from '@/components/VariableInput';

interface NodeConfigModalProps {
    visible: boolean;
    node: FlowNode | null;
    allNodes: FlowNode[];
    allEdges: FlowEdge[];
    onCancel: () => void;
    onOk: (nodeId: string, updatedData: Partial<FlowNodeData>) => void;
}

const NodeConfigModal: React.FC<NodeConfigModalProps> = ({
    visible,
    node,
    allNodes,
    allEdges,
    onCancel,
    onOk
}) => {
    const [loading, setLoading] = useState(false);
    const { toast } = useToast();
    
    // 固定的节点信息（不通过 schema，直接管理）
    const [nodeName, setNodeName] = useState('');
    const [description, setDescription] = useState('');
    
    // 动态数据源缓存
    const [dataSourceCache, setDataSourceCache] = useState<Record<string, DataSourceOption[]>>({});
    const [loadingDataSources, setLoadingDataSources] = useState(false);

    // ✅ 性能优化：使用 ref 保存 allNodes 和 allEdges 的最新引用
    // 避免这些频繁变化的数组导致 useCallback 重建
    const allNodesRef = useRef<FlowNode[]>(allNodes);
    const allEdgesRef = useRef<FlowEdge[]>(allEdges);
    
    useEffect(() => {
        allNodesRef.current = allNodes;
        allEdgesRef.current = allEdges;
    }, [allNodes, allEdges]);

    // 获取节点定义
    const nodeDefinition: WorkflowNodeDefinition | null = node?.data?.nodeDefinition || null;

    // ✅ 生成 Zod Schema（仅输入映射）
    const inputMappingSchema = useMemo(() => {
        if (!nodeDefinition || !isConfigurableNode(nodeDefinition) || !nodeDefinition.inputMappingSchema) {
            return null;
        }
        return convertJsonSchemaToZod(nodeDefinition.inputMappingSchema);
    }, [nodeDefinition]);

    // ✅ 创建表单实例（仅输入映射）
    const inputForm = useForm({
        resolver: inputMappingSchema ? zodResolver(inputMappingSchema) : undefined,
        defaultValues: {}
    });

    // ✅ 预加载动态数据源（仅输入映射）
    useEffect(() => {
        if (!visible || !nodeDefinition) return;

        const loadDynamicData = async () => {
            const inputTypes = isConfigurableNode(nodeDefinition) && nodeDefinition.inputMappingSchema
                ? extractDataSourceTypes(nodeDefinition.inputMappingSchema)
                : [];
            
            if (inputTypes.length === 0) {
                return;
            }

            setLoadingDataSources(true);
            
            const cache: Record<string, DataSourceOption[]> = {};
            let failedCount = 0;
            
            // ✅ 改进：单独处理每个数据源的加载，避免一个失败影响全部
            await Promise.allSettled(
                inputTypes.map(async (type) => {
                    try {
                        const data = await loadDataSource(type as DataSourceType);
                        cache[type] = data;
                    } catch (error) {
                        console.error(`加载数据源 ${type} 失败:`, error);
                        failedCount++;
                        cache[type] = []; // 失败时使用空数组
                    }
                })
            );
            
            setDataSourceCache(cache);
            setLoadingDataSources(false);
            
            // 如果有失败的数据源，显示提示
            if (failedCount > 0) {
                toast({
                    title: '部分数据加载失败',
                    description: `${failedCount} 个选项数据加载失败，请检查网络后重新打开节点配置`,
                    variant: 'destructive'
                });
            }
        };

        loadDynamicData();
    }, [visible, nodeDefinition, toast]);

    // ✅ 初始化表单数据
    useEffect(() => {
        if (visible && node && nodeDefinition) {
            const nodeData = node.data || {};
            
            // 设置固定节点信息（从 configs 或 nodeDefinition 获取）
            setNodeName(nodeData.configs?.nodeName || nodeDefinition.nodeName);
            setDescription(nodeData.configs?.description || nodeDefinition.description || '');
            
            // 设置输入映射默认值（转换 UUID 为显示名称）
            if (isConfigurableNode(nodeDefinition)) {
                const displayInputMapping = convertObjectToDisplayName(
                    nodeData.inputMapping || {},
                    allNodes
                );
                inputForm.reset(displayInputMapping);
            }
        }
        // 只在 visible 或 node.id 改变时重置表单
        // allNodes 改变不应该触发重置（用户正在编辑时）
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [visible, node?.id]);

    // ✅ 保存配置
    const handleSave = () => {
        if (!node || !nodeDefinition) return;
        
        // 验证节点名称（必填）
        if (!nodeName || !nodeName.trim()) {
            toast({
                title: '保存失败',
                description: '节点名称不能为空',
                variant: 'destructive'
            });
            return;
        }
        
        // 使用 handleSubmit 验证输入映射（如果存在）
        const submitForm = async () => {
            setLoading(true);
            try {
                // 获取输入映射数据
                let inputData = {};
                if (isConfigurableNode(nodeDefinition) && nodeDefinition.inputMappingSchema) {
                    inputData = inputForm.getValues();
                }

                // 转换显示名称格式为 UUID 格式（仅输入映射需要）
                const uuidInputMapping = convertObjectToUUID(inputData as Record<string, any>, allNodes);

                // 构建 configs（包含元数据）
                const configs = {
                    nodeName: nodeName.trim(),
                    nodeCode: nodeDefinition.nodeCode, // 只读，从定义获取
                    description: description.trim()
                };

                // 构建更新数据
            const updatedData: Partial<FlowNodeData> = {
                    label: nodeName.trim(),
                configs,
                    inputMapping: uuidInputMapping,
                    outputs: isConfigurableNode(nodeDefinition) ? nodeDefinition.outputs || [] : []
            };

            onOk(node.id, updatedData);
                
                toast({
                    title: '保存成功',
                    description: '节点配置已更新'
                });
                
                // 关闭抽屉
            onCancel();
        } catch (error) {
                console.error('保存节点配置失败:', error);
                toast({
                    title: '保存失败',
                    description: '请检查必填字段是否填写完整',
                    variant: 'destructive'
                });
        } finally {
            setLoading(false);
        }
    };

        // 如果有输入映射schema，使用表单验证
        if (inputMappingSchema) {
            inputForm.handleSubmit(submitForm)();
        } else {
            submitForm();
        }
    };

    // ✅ 重置表单
    const handleReset = () => {
        if (!node || !nodeDefinition) return;
        
        // 重置节点信息
        setNodeName(nodeDefinition.nodeName);
        setDescription(nodeDefinition.description || '');
        
        // 重置输入映射
        inputForm.reset({});
        
        toast({
            title: '已重置',
            description: '表单已恢复为默认值'
        });
    };

    // ✅ 通用 Select 渲染函数（减少代码重复）
    const renderSelect = useCallback((
        options: Array<{ label: string; value: any }>,
        field: any,
        prop: any,
        disabled: boolean,
        onValueChange?: (value: string) => void
    ) => (
        <Select
            disabled={disabled}
            value={field.value?.toString()}
            onValueChange={onValueChange || field.onChange}
        >
            <SelectTrigger>
                <SelectValue placeholder={`请选择${prop.title || ''}`} />
            </SelectTrigger>
            <SelectContent>
                {options.map((option) => (
                    <SelectItem key={option.value} value={option.value.toString()}>
                        {option.label}
                    </SelectItem>
                ))}
            </SelectContent>
        </Select>
    ), []);

    // ✅ 渲染字段控件
    const renderFieldControl = useCallback((prop: any, field: any, key: string) => {
        // 动态数据源
        if (prop['x-dataSource']) {
            const options = dataSourceCache[prop['x-dataSource']] || [];
            return renderSelect(
                options,
                field,
                prop,
                loadingDataSources || loading,
                (value) => {
                    // 如果是数字类型，转换为数字
                    const numValue = Number(value);
                    field.onChange(isNaN(numValue) ? value : numValue);
                }
            );
        }

        // 静态枚举值
        if (prop.enum && Array.isArray(prop.enum)) {
            const options = prop.enum.map((value: any, index: number) => {
                const enumValue = typeof value === 'object' ? value.value : value;
                const enumLabel = typeof value === 'object' ? value.label : (prop.enumNames?.[index] || value);
                return { label: enumLabel, value: enumValue };
            });
            return renderSelect(options, field, prop, loading);
        }

        // 根据类型渲染
            switch (prop.type) {
                case 'string': {
                    // 黑名单字段：不使用变量输入
                    const blacklist = ['nodeName', 'nodeCode', 'description'];
                    const isBlacklisted = blacklist.includes(key);
                    const isPassword = prop.format === 'password';
                    
                    // 密码字段或黑名单字段：使用普通输入
                    if (isPassword || isBlacklisted) {
                        if (prop.format === 'textarea' || key.includes('description')) {
                            return (
                                <Textarea
                                    {...field}
                                    disabled={loading}
                                    placeholder={prop.description || `请输入${prop.title || ''}`}
                                    rows={3}
                                />
                            );
                        }
                        return (
                            <Input
                                {...field}
                                type={isPassword ? 'password' : 'text'}
                                disabled={loading}
                                placeholder={prop.description || `请输入${prop.title || ''}`}
                            />
                        );
                    }
                    
                    // 其他字符串字段：使用 VariableInput
                    const isTextarea = prop.format === 'textarea' || 
                                     ['content', 'body', 'expression', 'script'].includes(key);
                    
                    return (
                        <VariableInput
                            value={field.value || ''}
                            onChange={field.onChange}
                            allNodes={allNodesRef.current}
                            allEdges={allEdgesRef.current}
                            currentNodeId={node?.id || ''}
                            variant={isTextarea ? 'textarea' : 'input'}
                            placeholder={prop.description || `请输入${prop.title || ''}`}
                            disabled={loading}
                            rows={3}
                        />
                    );
                }
            
                case 'number':
                case 'integer':
                return (
                    <Input
                        {...field}
                        type="number"
                        disabled={loading}
                        placeholder={prop.description || `请输入${prop.title || ''}`}
                        onChange={(e) => {
                            const value = e.target.value;
                            field.onChange(value === '' ? undefined : Number(value));
                        }}
                    />
                );
            
                case 'boolean':
                return (
                    <input
                        type="checkbox"
                        checked={field.value || false}
                        disabled={loading}
                        onChange={(e) => field.onChange(e.target.checked)}
                        className="h-4 w-4"
                    />
                );
            
                default:
                return (
                    <Input
                        {...field}
                        disabled={loading}
                        placeholder={prop.description || `请输入${prop.title || ''}`}
                    />
                );
        }
    }, [dataSourceCache, loadingDataSources, loading, node, renderSelect]);

    // ✅ 渲染表单字段
    const renderFormFields = useCallback((
        schema: JSONSchema,
        form: ReturnType<typeof useForm>,
        prefix: string = ''
    ) => {
        if (!schema.properties || typeof schema.properties !== 'object') {
            return null;
        }

        return Object.entries(schema.properties).map(([key, prop]: [string, any]) => {
            const fieldName = prefix ? `${prefix}.${key}` : key;
            const isRequired = Array.isArray(schema.required) && schema.required.includes(key);

            return (
                <FormField
                    key={fieldName}
                    control={form.control}
                    name={fieldName}
                    render={({ field }) => (
                        <FormItem>
                            <FormLabel>
                                {prop.title || key}
                                {isRequired && <span className="text-red-500 ml-1">*</span>}
                            </FormLabel>
                            <FormControl>
                                {renderFieldControl(prop, field, key)}
                            </FormControl>
                            {prop.description && (
                                <FormDescription>{prop.description}</FormDescription>
                            )}
                            <FormMessage />
                        </FormItem>
                    )}
                />
            );
        });
    }, [renderFieldControl]);

    if (!nodeDefinition) {
        return null;
    }

    return (
        <Sheet open={visible} onOpenChange={(open) => !open && onCancel()}>
            <SheetContent className="w-[600px] sm:max-w-[600px] flex flex-col p-0">
                {/* Header - 固定在顶部 */}
                <div className="px-6 pt-6 pb-4 border-b">
                    <SheetHeader className="space-y-2">
                        <SheetTitle className="text-xl font-semibold">
                            编辑节点 - {nodeDefinition.nodeName}
                        </SheetTitle>
                        <SheetDescription>
                            配置节点的参数和映射关系
                        </SheetDescription>
                    </SheetHeader>
                </div>

                {/* Content - 可滚动区域 */}
                <div className="flex-1 overflow-y-auto px-6 py-4">
                    <Accordion 
                        type="multiple" 
                        defaultValue={["info", "input"]} 
                        className="w-full"
                    >
                        {/* 节点信息（固定表单，不通过 schema） */}
                        <AccordionItem value="info" className="border-b">
                            <AccordionTrigger className="text-base font-semibold flex-row-reverse justify-end gap-2 hover:no-underline">
                                节点信息
                            </AccordionTrigger>
                            <AccordionContent className="px-1 space-y-4">
                                {/* 节点编码（只读） */}
                                <div className="space-y-2">
                                    <label className="text-sm font-medium">
                                        节点编码
                                    </label>
                                    <Input
                                        value={nodeDefinition.nodeCode}
                                        disabled
                                        className="bg-muted cursor-not-allowed"
                                    />
                                    <p className="text-xs text-muted-foreground">
                                        节点的唯一标识符（只读）
                                    </p>
                </div>

                                {/* 节点名称 */}
                                <div className="space-y-2">
                                    <label className="text-sm font-medium">
                                        节点名称 <span className="text-red-500">*</span>
                                    </label>
                                    <Input
                                        value={nodeName}
                                        onChange={(e) => setNodeName(e.target.value)}
                                        placeholder="请输入节点名称"
                                        disabled={loading}
                                    />
                                    <p className="text-xs text-muted-foreground">
                                        节点在流程图中显示的名称
                                    </p>
                    </div>

                                {/* 节点描述 */}
                                <div className="space-y-2">
                                    <label className="text-sm font-medium">
                                        节点描述
                                    </label>
                                    <Textarea
                                        value={description}
                                        onChange={(e) => setDescription(e.target.value)}
                                        placeholder="请输入节点描述"
                                        disabled={loading}
                                        rows={3}
                                    />
                                    <p className="text-xs text-muted-foreground">
                                        节点的详细说明
                                    </p>
                    </div>
                            </AccordionContent>
                        </AccordionItem>

                        {/* 输入映射 */}
                        {isConfigurableNode(nodeDefinition) && nodeDefinition.inputMappingSchema && (
                            <AccordionItem value="input" className="border-b">
                                <AccordionTrigger className="text-base font-semibold flex-row-reverse justify-end gap-2 hover:no-underline">
                                    输入
                                </AccordionTrigger>
                                <AccordionContent className="px-1 space-y-4">
                                    <Form {...inputForm}>
                                        {renderFormFields(nodeDefinition.inputMappingSchema, inputForm)}
                                    </Form>
                                </AccordionContent>
                            </AccordionItem>
                        )}

                        {/* 输出 - 只读展示 */}
                        {isConfigurableNode(nodeDefinition) && nodeDefinition.outputs && nodeDefinition.outputs.length > 0 && (
                            <AccordionItem value="output" className="border-b">
                                <AccordionTrigger className="text-base font-semibold flex-row-reverse justify-end gap-2 hover:no-underline">
                                    输出
                                </AccordionTrigger>
                                <AccordionContent className="px-1">
                                    <div className="text-sm text-muted-foreground mb-4 p-3 bg-muted/50 rounded-md">
                                        💡 此节点执行后会产生以下数据，可以通过 <code className="px-1 py-0.5 bg-background rounded">{'${节点名.字段名}'}</code> 引用这些数据
                    </div>
                                    <div className="space-y-3">
                                        {nodeDefinition.outputs.map((output) => (
                                            <div key={output.name} className="p-3 border rounded-md bg-background">
                                                <div className="flex items-start justify-between mb-2">
                                                    <div className="flex-1">
                                                        <div className="flex items-center gap-2">
                                                            <span className="font-medium text-foreground">{output.title}</span>
                                                            <code className="px-1.5 py-0.5 text-xs bg-muted rounded">{output.name}</code>
                                                            <span className="text-xs text-muted-foreground border border-border px-1.5 py-0.5 rounded">
                                                                {output.type}
                    </span>
                                                            {output.required && (
                                                                <span className="text-xs text-red-500">*</span>
                                                            )}
                                                        </div>
                                                        <p className="text-sm text-muted-foreground mt-1">
                                                            {output.description}
                                                        </p>
                                                    </div>
                                                </div>
                                                {output.enum && (
                                                    <div className="mt-2 text-xs">
                                                        <span className="text-muted-foreground">可选值：</span>
                                                        <span className="ml-1 text-foreground">{output.enum.join(', ')}</span>
                                                    </div>
                                                )}
                                                {output.example !== undefined && (
                                                    <div className="mt-2 text-xs">
                                                        <span className="text-muted-foreground">示例：</span>
                                                        <code className="ml-1 px-1.5 py-0.5 bg-muted rounded text-foreground">
                                                            {typeof output.example === 'object'
                                                                ? JSON.stringify(output.example)
                                                                : String(output.example)}
                                                        </code>
                                                    </div>
                                                )}
                                            </div>
                                        ))}
                                    </div>
                                </AccordionContent>
                            </AccordionItem>
                        )}
                    </Accordion>
                </div>

                {/* Footer - 固定在底部 */}
                <SheetFooter className="px-6 py-4 border-t bg-background">
                    <div className="flex justify-between w-full">
                    <Button 
                            type="button"
                            variant="outline"
                        onClick={handleReset}
                            disabled={loading}
                    >
                            <RotateCcw className="mr-2 h-4 w-4" />
                        重置
                    </Button>
                        <div className="flex gap-2">
                            <Button
                                type="button"
                                variant="outline"
                                onClick={onCancel}
                                disabled={loading}
                            >
                            取消
                        </Button>
                        <Button 
                                type="button"
                                onClick={handleSave}
                                disabled={loading || loadingDataSources}
                            >
                                <Save className="mr-2 h-4 w-4" />
                                {loading ? '保存中...' : '保存配置'}
                        </Button>
                </div>
            </div>
                </SheetFooter>
            </SheetContent>
        </Sheet>
    );
};

export default NodeConfigModal;
