'use client';

import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import dynamic from 'next/dynamic';
import { motion, AnimatePresence } from 'framer-motion';
import { Film, Image as ImageIcon, MessageSquare, Mic2, Music2, Workflow } from 'lucide-react';
import { cn } from '@/utils';
import { useModelStore } from '@lib/store/modelStore';
import { sendChatMessage } from './services/canvasService';
import { Message } from './utils/chatUtils';
import { useReactFlow, useNodes, useEdges } from '@xyflow/react';
import { AppNodeData, NodeType, NodeStatus, AppNodeType } from './types/node';
import { retryWithBackoff, parseApiError, ErrorCode } from '@/lib/errors';
import { processPromptWithAssets } from './utils';
import { buildInputAssets } from './interaction-input-helpers';

import { AssetSelector } from './controls/interaction-input/AssetSelector';
import { CollapsedView } from './controls/interaction-input/CollapsedView';
import { AutoResizeTextarea } from './controls/interaction-input/AutoResizeTextarea';
import { InputFooter } from './controls/interaction-input/InputFooter';
import { useStyles } from '@lib/hooks/useConfig';
import { StyleConfig } from '@/types';
import { InputAsset } from './types/node';
import { 
    ModelSelector, ResolutionSelector, ImageResolutionSelector, AspectRatioSelector, 
    DurationSelector, CountSelector, StyleSelector,
    CameraControlSelector, ShotTypeToggle, AudioToggle, VoiceSelector
} from './controls/interaction-input/Selectors';
import { 
    GenerationSettings, 
    GenerationType, 
    InteractionInputProps 
} from './controls/interaction-input/types';
import { DEFAULT_SETTINGS } from './controls/interaction-input/constants';

import { InputThumbnails } from './nodes/components/InputThumbnails';
import { TabButton } from './controls/interaction-input/TabButton';
import { styles as uiStyles } from '@/styles/constants';
import { useWorkflow } from '@lib/hooks/useWorkflow';
import { useSelectedNode } from './hooks/useSelectedNode';
import { useNodeData } from './hooks/useNodeData';
import { useNodeExecution } from './hooks/useNodeExecution';
import { useAgentCanvasActions } from './hooks/useAgentCanvasActions';
import { useInteractionDefaults } from './hooks/useInteractionDefaults';
import { useInteractionEditMode } from './hooks/useInteractionEditMode';
import { DefaultService } from '@lib/api';
import { logger } from '@/lib/utils/logger';

const ChatDisplay = dynamic(
  () => import('./controls/interaction-input/ChatDisplay').then(m => ({ default: m.ChatDisplay })),
  { ssr: false }
);

const InteractionInputComponent = ({ onGenerate }: InteractionInputProps) => {
  const { imageModels, videoModels, audioModels, lyricsModels, musicModels, llmModels } = useModelStore();
  const { data: stylesData } = useStyles();
  const styleConfigs = (stylesData?.styles || []) as StyleConfig[];
  const [activeTab, setActiveTab] = useState<GenerationType>('text');
  const [inputText, setInputText] = useState('');
  const [selectedAssets, setSelectedAssets] = useState<string[]>([]);
  const [isGenerating, setIsGenerating] = useState(false);
  const [error, setError] = useState<string | null>(null);
  
  // Chat State
  const [messages, setMessages] = useState<Message[]>([]);
  const [isChatLoading, setIsChatLoading] = useState(false);
  const [showChat, setShowChat] = useState(false);

  // Expand/Collapse State
  const [isExpanded, setIsExpanded] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  // Settings State
  const [settings, setSettings] = useState<GenerationSettings>(DEFAULT_SETTINGS);

  // --- Edit Mode: Selected Node ---
  const { selectedNode, selectedNodeData, selectedNodeId, isEditMode } = useSelectedNode();
  const { update: updateNodeData } = useNodeData(selectedNodeId || '__noop__');
  const { executeNode } = useNodeExecution();

  // 任务状态绑定当前选中节点：编辑态由节点 status/taskId 推导，非编辑态用全局 isGenerating（创建节点等）
  const isGeneratingForBar = isEditMode
    ? (selectedNodeData?.status === 'WORKING' || !!selectedNodeData?.taskId)
    : isGenerating;

  const isLyricsEditNode = selectedNodeData?.type === NodeType.LYRICS_GENERATOR;
  const isMusicEditNode =
    selectedNodeData?.type === NodeType.AUDIO_GENERATOR && selectedNodeData?.generationType === 'music';

  const { handleInputChange, effectiveSetSettings, clearPromptSync } = useInteractionEditMode({
    isEditMode,
    selectedNodeId,
    selectedNodeData: selectedNodeData ?? undefined,
    updateNodeData,
    inputText,
    settings,
    activeTab,
    setInputText,
    setSettings,
    setActiveTab,
    setIsExpanded,
    defaultSettings: DEFAULT_SETTINGS,
  });

  // When entering edit mode, close chat
  useEffect(() => {
    if (isEditMode && selectedNodeData) setShowChat(false);
  }, [isEditMode, selectedNodeData]);

  const toggleMusicLyricsMode = useCallback(() => {
    const nextLyrics = !(settings.musicGenerateLyrics ?? false);
    const currentMusic = settings.musicGenerateMusic ?? true;
    if (!nextLyrics && !currentMusic) return;

    effectiveSetSettings({
      ...settings,
      musicGenerateLyrics: nextLyrics,
      model: currentMusic
        ? (settings.musicModel || settings.model)
        : (nextLyrics ? (settings.lyricsModel || settings.model) : settings.model),
    });
  }, [effectiveSetSettings, settings]);

  const toggleMusicSongMode = useCallback(() => {
    const currentLyrics = settings.musicGenerateLyrics ?? false;
    const nextMusic = !(settings.musicGenerateMusic ?? true);
    if (!currentLyrics && !nextMusic) return;

    effectiveSetSettings({
      ...settings,
      musicGenerateMusic: nextMusic,
      model: nextMusic
        ? (settings.musicModel || settings.model)
        : (currentLyrics ? (settings.lyricsModel || settings.model) : settings.model),
    });
  }, [effectiveSetSettings, settings]);

  const handleLyricsModelSelect = useCallback((id: string) => {
    effectiveSetSettings({
      ...settings,
      lyricsModel: id,
      musicTarget: 'lyrics',
      musicGenerateLyrics: true,
      musicGenerateMusic: false,
      model: id,
    });
  }, [effectiveSetSettings, settings]);

  const handleMusicModelSelect = useCallback((id: string) => {
    effectiveSetSettings({
      ...settings,
      musicModel: id,
      musicTarget: 'music',
      musicGenerateMusic: true,
      musicGenerateLyrics: false,
      model: id,
    });
  }, [effectiveSetSettings, settings]);

  // Get available models based on active tab
  const availableModels = useMemo(() => {
    logger.debug('[InteractionInput] Computing availableModels for tab:', activeTab);
    if (isEditMode && isLyricsEditNode) return lyricsModels;
    if (isEditMode && isMusicEditNode) return musicModels;
    if (activeTab === 'text') return llmModels;
    if (activeTab === 'image') return imageModels;
    if (activeTab === 'video') return videoModels;
    if (activeTab === 'audio') return audioModels;
    if (activeTab === 'music') {
      return (settings.musicGenerateMusic ?? true) ? musicModels : lyricsModels;
    }
    return llmModels;
  }, [
    activeTab,
    isEditMode,
    isLyricsEditNode,
    isMusicEditNode,
    settings.musicGenerateMusic,
    imageModels,
    videoModels,
    audioModels,
    lyricsModels,
    musicModels,
    llmModels
  ]);
  
  // Get current model config for capability-based controls
  const currentModelConfig = useMemo(() => {
    if (!settings.model || !availableModels) return null;
    return availableModels[settings.model];
  }, [settings.model, availableModels]);

  const capabilities = currentModelConfig?.capabilities;
  const inputPlaceholder = useMemo(() => {
    if (activeTab === 'music') {
      const generateLyrics = settings.musicGenerateLyrics ?? false;
      const generateMusic = settings.musicGenerateMusic ?? true;
      if (generateLyrics && generateMusic) return '输入主题/风格，先生成歌词再生成音乐';
      if (generateLyrics) return '输入主题或风格，生成歌词';
      return '输入歌词，生成音乐';
    }
    return isExpanded ? '输入你的创意' : '有什么可以帮您？';
  }, [activeTab, isExpanded, settings.musicGenerateLyrics, settings.musicGenerateMusic]);

  // React Flow hooks for node and edge operations
  const { getNodes } = useReactFlow();
  
  // Workflow orchestration hook | 工作流编排 hook
  const workflow = useWorkflow({
    getDefaultImageModel: () => Object.values(imageModels).find(m => m.is_default)?.id || Object.keys(imageModels)[0] || '',
    getDefaultVideoModel: () => Object.values(videoModels).find(m => m.is_default)?.id || Object.keys(videoModels)[0] || '',
  });

  // Get input assets for the selected node
  const edges = useEdges();
  const nodes = useNodes();
  
  const inputAssets = useMemo(() => {
      return buildInputAssets({
        isEditMode,
        selectedNodeId,
        edges,
        nodes,
        audioModels,
      });
  }, [isEditMode, selectedNodeId, edges, nodes, audioModels]);
  
  // Track processed message indices to avoid duplicate node creation
  const processedIndices = useRef(new Set<number>());
  
  // Auto-collapse on outside click (not in edit mode - edit mode is controlled by node selection)
  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      const target = event.target as Element;
      if (!document.contains(target)) return;

      if (
        containerRef.current && 
        !containerRef.current.contains(target) &&
        !target.closest('.interaction-model-popover')
      ) {
        if (!isEditMode) {
          setIsExpanded(false);
        }
        setShowChat(false);
      }
    }
    document.addEventListener("mousedown", handleClickOutside, true);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside, true);
    };
  }, [isEditMode]);
  
  useInteractionDefaults(activeTab, availableModels, lyricsModels, musicModels, setSettings, isEditMode);

  const toggleAsset = (id: string) => {
    setSelectedAssets(prev => 
      prev.includes(id) ? prev.filter(r => r !== id) : [...prev, id]
    );
  };

  // Agent 画布操作（节点/边/工作流/actions 解析与应用）
  const { processDeleteNodes, processUpdateNode, processWorkflow, processAgentCommands } =
    useAgentCanvasActions();

  // Process AI messages for node creation commands
  useEffect(() => {
    if (!isChatLoading && messages.length > 0) {
        messages.forEach((msg, index) => {
            if (msg.role === 'model' && !processedIndices.current.has(index)) {
                processAgentCommands(msg.text);
                processedIndices.current.add(index);
            }
        });
    }
  }, [isChatLoading, messages, processAgentCommands]);

  // --- Get Selected Node Context ---
  
  const getSelectedContext = useCallback(() => {
      const nodes = getNodes();
      const selectedNodes = nodes.filter(node => node.selected);
      
      if (selectedNodes.length === 0) return "";
      
      const contextParts = selectedNodes.map(node => {
          const data = node.data as AppNodeData;
          let info = `- Node: ${data.title || node.type} (ID: ${node.id})`;
          if (data.prompt) info += `\n  Prompt: ${data.prompt}`;
          if (data.negativePrompt) info += `\n  Negative Prompt: ${data.negativePrompt}`;
          // Add more specific fields if needed
          return info;
      });
      
      return "\n\n[Current Context: Selected Nodes]\n" + contextParts.join('\n') + "\n";
  }, [getNodes]);

  const handleGenerate = async () => {
    if (!inputText.trim()) return;
    
    // Clear previous error
    setError(null);

    // --- Edit Mode: execute the selected node（状态由节点 status/taskId 驱动，不写全局 isGenerating）---
    if (isEditMode && selectedNodeId) {
      try {
        clearPromptSync();
        const isPromptGen = selectedNodeData?.type === 'PROMPT_GENERATOR';
        updateNodeData(isPromptGen ? { userPrompt: inputText } : { prompt: inputText });
        await new Promise(r => setTimeout(r, 50));
        await executeNode(selectedNodeId);
        setError(null);
      } catch (e: unknown) {
        console.error("Node execution failed", e);
        const parsedError = parseApiError(e);
        setError(parsedError.message);
      }
      return;
    }
    
    if (activeTab === 'text') {
        const userText = inputText;
        setInputText('');
        setShowChat(true);

        // Inject context if available
        const context = getSelectedContext();
        const finalUserText = context ? `${userText}\n${context}` : userText;

        // Display original user text in UI, but send enhanced text to backend
        const newMessages: Message[] = [...messages, { 
            role: 'user', 
            text: userText,
            fullText: context ? finalUserText : undefined
        }];
        setMessages(newMessages);
        setIsChatLoading(true);

        try {
            // Build history payload
            const historyPayload = messages.map(m => ({ 
                role: m.role, 
                parts: [{ text: m.fullText || m.text }] 
            }));

            // Add placeholder for assistant message
            setMessages(prev => [...prev, { role: 'model', text: '' }]);

            // Use the prepared text (with context if any) as the new message
            const messagePayload = context ? finalUserText : userText;

            // Wrap sendChatMessage with retry logic
            await retryWithBackoff(
                () => sendChatMessage(historyPayload, messagePayload, {
                    onChunk: (chunk) => {
                         setMessages(prev => {
                             const newMsgs = [...prev];
                             const lastIndex = newMsgs.length - 1;
                             const lastMsg = newMsgs[lastIndex];
                             
                             if (lastMsg && lastMsg.role === 'model') {
                                 newMsgs[lastIndex] = {
                                     ...lastMsg,
                                     text: lastMsg.text + chunk
                                 };
                                 return newMsgs;
                             }
                             return prev;
                         });
                    }
                }),
                {
                    maxRetries: 2,
                    initialDelay: 1000,
                    retryableErrors: [ErrorCode.NETWORK_ERROR, ErrorCode.TIMEOUT_ERROR, ErrorCode.SERVICE_UNAVAILABLE]
                }
            );
        } catch (e: unknown) {
             console.error("Chat failed", e);
             const parsedError = parseApiError(e);
             const errorMessage = parsedError.message || "连接错误，请稍后重试。";
             
             setError(errorMessage);
             setMessages(prev => {
                 const last = prev[prev.length - 1];
                 if (last.role === 'model' && !last.text) {
                     return [...prev.slice(0, -1), { role: 'model', text: `❌ ${errorMessage}` }];
                 }
                 return prev;
            });
        } finally {
            setIsChatLoading(false);
        }
        return;
    }

    setIsGenerating(true);
    const generatePrompt = inputText;
    setInputText('');
    setIsExpanded(false);
    
    try {
      if (onGenerate) {
        // 处理 prompt 中通过 @别名 引用到的素材
        const { processedPrompt, mappings } = processPromptWithAssets(generatePrompt, inputAssets);

        await retryWithBackoff(
            () => onGenerate({
              type: activeTab,
              prompt: processedPrompt,
              settings: settings,
              inputAssets: inputAssets,
              assetMappings: mappings
            }),
            {
                maxRetries: 2,
                initialDelay: 2000,
                retryableErrors: [ErrorCode.NETWORK_ERROR, ErrorCode.TIMEOUT_ERROR, ErrorCode.PROVIDER_ERROR]
            }
        );
        setError(null);
      }
    } catch (e: unknown) {
      console.error("Generation failed", e);
      const parsedError = parseApiError(e);
      setError(parsedError.message);
    } finally {
      setIsGenerating(false);
    }
  };

  const handleClearChat = () => {
    setMessages([]);
    // Optional: Keep current input text or clear it? 
    // Usually restart means fresh start, but keeping input allows retrying.
    // User said "清空上下文", so messages only is safe.
    // Let's also close the chat bubbles if open, to simulate a full reset?
    // "重新开始对话" implies the chat history is gone.
  };

  // Handle workflow generation (Cmd/Ctrl + Enter in text mode)
  // Analyzes user input and automatically creates workflow nodes
  const handleWorkflowGenerate = async () => {
    if (!inputText.trim() || workflow.isAnalyzing || workflow.isExecuting) return;
    
    const userText = inputText;
    setInputText('');
    setError(null);
    
    // Show feedback in chat
    setShowChat(true);
    setMessages(prev => [...prev, { 
      role: 'user', 
      text: `[工作流] ${userText}` 
    }]);
    
    try {
      // Add status message
      setMessages(prev => [...prev, { 
        role: 'model', 
        text: '正在分析工作流...' 
      }]);
      
      // Run workflow orchestration
      await workflow.runWorkflow(userText);
      
      // Update status message
      setMessages(prev => {
        const newMsgs = [...prev];
        const lastIndex = newMsgs.length - 1;
        if (newMsgs[lastIndex]?.role === 'model') {
          newMsgs[lastIndex] = {
            ...newMsgs[lastIndex],
            text: '✅ 工作流已创建！节点已自动布局在画布上。'
          };
        }
        return newMsgs;
      });
    } catch (e: unknown) {
      console.error("Workflow failed", e);
      setError((e instanceof Error ? e.message : null) ?? '工作流执行失败');
      
      // Update status message with error
      setMessages(prev => {
        const newMsgs = [...prev];
        const lastIndex = newMsgs.length - 1;
        if (newMsgs[lastIndex]?.role === 'model') {
          newMsgs[lastIndex] = {
            ...newMsgs[lastIndex],
            text: `❌ 工作流失败: ${e instanceof Error ? e.message : '未知错误'}`
          };
        }
        return newMsgs;
      });
    }
  };

  return (
      <div 
        ref={containerRef} 
        className="w-full max-w-[760px] z-10 px-4 pointer-events-none"
        onFocusCapture={() => setShowChat(true)}
      >
        
        {/* Error Display */}
        {error && (
            <div className="mb-3 pointer-events-auto">
                <div className="bg-red-500/10 border border-red-500/20 rounded-lg px-4 py-2 backdrop-blur-md">
                    <div className="flex items-center gap-2">
                        <span className="text-red-400 text-sm">⚠️ {error}</span>
                        <button 
                            onClick={() => setError(null)}
                            className="ml-auto text-red-400 hover:text-red-300 transition-colors"
                        >
                            ✕
                        </button>
                    </div>
                </div>
            </div>
        )}
        
        {/* Top Controls */}
        <div className="flex items-end justify-between relative">
            <AssetSelector 
                isExpanded={isExpanded} 
                selectedAssets={selectedAssets} 
                onToggleAsset={toggleAsset} 
                inputAssets={inputAssets}
            />

            {/* Chat Overlay Display */}
            <AnimatePresence>
                {activeTab === 'text' && showChat && (
                    <ChatDisplay messages={messages} isLoading={isChatLoading} />
                )}
            </AnimatePresence>

            <AnimatePresence>
                {isExpanded && (
                    <motion.div 
                        layout
                        initial={{ opacity: 0, y: 10 }}
                        animate={{ opacity: 1, y: 0 }}
                        exit={{ opacity: 0, y: 10 }}
                        transition={{ duration: 0.2 }}
                        className={`flex items-center gap-1 ${uiStyles.glassPanel} p-1.5 ${uiStyles.roundedFull} pointer-events-auto mb-3`}
                    >
                         <TabButton
                            isActive={activeTab === 'text'}
                            onClick={() => { 
                                setActiveTab('text'); 
                                setShowChat(true); 
                                setIsExpanded(false); // Switch to collapsed text mode
                            }}
                            icon={<MessageSquare className="w-3.5 h-3.5" />}
                            label="助手"
                            disabled={isEditMode}
                         />
                         <TabButton
                            isActive={activeTab === 'image'}
                            onClick={() => setActiveTab('image')}
                            icon={<ImageIcon className="w-3.5 h-3.5" />}
                            label="图片"
                            disabled={isEditMode}
                         />
                         <TabButton
                            isActive={activeTab === 'video'}
                            onClick={() => setActiveTab('video')}
                            icon={<Film className="w-3.5 h-3.5" />}
                            label="视频"
                            disabled={isEditMode}
                         />
                         <TabButton
                            isActive={activeTab === 'audio'}
                            onClick={() => setActiveTab('audio')}
                            icon={<Mic2 className="w-3.5 h-3.5" />}
                            label="音频"
                            disabled={isEditMode}
                         />
                         <TabButton
                            isActive={activeTab === 'music'}
                            onClick={() => setActiveTab('music')}
                            icon={<Music2 className="w-3.5 h-3.5" />}
                            label="音乐"
                            disabled={isEditMode}
                         />
                    </motion.div>
                )}
            </AnimatePresence>
        </div>

        {/* Input Assets Display (Collapsed Mode) */}
        <AnimatePresence>
            {!isExpanded && inputAssets.length > 0 && (
                <motion.div
                    initial={{ opacity: 0, y: 10 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: 10 }}
                    className="mb-2 pointer-events-auto"
                >
                    <InputThumbnails assets={inputAssets} onReorder={() => {}} />
                </motion.div>
            )}
        </AnimatePresence>

        {/* Settings Bar for Collapsed Media Mode - Only Model Selector */}
        <AnimatePresence>
            {!isExpanded && (activeTab === 'image' || activeTab === 'video' || activeTab === 'audio' || activeTab === 'music' || activeTab === 'text') && (
                <motion.div
                    initial={{ opacity: 0, y: 10 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: 10 }}
                    className="flex justify-center mb-3 pointer-events-auto"
                >
                    <div className="flex items-center gap-2 bg-black/40 backdrop-blur-md p-1.5 rounded-full border border-white/10 shadow-lg">
                        {/* Edit mode indicator */}
                        {isEditMode && selectedNodeData && (
                            <>
                                <div className="flex items-center gap-1 px-2 py-0.5 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-[10px] font-bold text-cyan-400">
                                    <span className="truncate max-w-[80px]">{selectedNodeData.title}</span>
                                </div>
                                <div className="h-4 w-[1px] bg-white/10 mx-1" />
                            </>
                        )}

                        {activeTab === 'music' && !isEditMode ? (
                            <>
                                <div className="flex items-center gap-1">
                                    <span
                                        onClick={toggleMusicLyricsMode}
                                        className={cn(
                                            "text-[10px] px-2 py-1 rounded-full cursor-pointer transition-colors",
                                            (settings.musicGenerateLyrics ?? false)
                                                ? "bg-cyan-500/20 text-cyan-300 border border-cyan-500/30"
                                                : "text-muted-foreground hover:text-foreground hover:bg-white/5 border border-transparent"
                                        )}
                                    >
                                        歌词模型
                                    </span>
                                    <ModelSelector
                                        selectedModelId={settings.lyricsModel || ''}
                                        models={lyricsModels}
                                        onSelect={handleLyricsModelSelect}
                                    />
                                </div>

                                <div className="h-4 w-[1px] bg-white/10 mx-1" />

                                <div className="flex items-center gap-1">
                                    <span
                                        onClick={toggleMusicSongMode}
                                        className={cn(
                                            "text-[10px] px-2 py-1 rounded-full cursor-pointer transition-colors",
                                            (settings.musicGenerateMusic ?? true)
                                                ? "bg-cyan-500/20 text-cyan-300 border border-cyan-500/30"
                                                : "text-muted-foreground hover:text-foreground hover:bg-white/5 border border-transparent"
                                        )}
                                    >
                                        歌曲模型
                                    </span>
                                    <ModelSelector
                                        selectedModelId={settings.musicModel || ''}
                                        models={musicModels}
                                        onSelect={handleMusicModelSelect}
                                    />
                                </div>
                            </>
                        ) : (
                            <>
                                <ModelSelector
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                    onSelect={(id) => effectiveSetSettings({ ...settings, model: id })}
                                />
                                {/* Divider for all tabs */}
                                <div className="h-4 w-[1px] bg-white/10 mx-1" />
                            </>
                        )}

                        {/* Text/Assistant: Show LLM-specific controls */}
                        {activeTab === 'text' && (
                            <>
                                {/* Temperature control could be added here */}
                                {/* For now, just showing model selector is sufficient */}
                            </>
                        )}

                        {/* Image: Resolution, Aspect Ratio, Style, Count */}
                        {activeTab === 'image' && (
                            <>
                                <ImageResolutionSelector 
                                    resolution={settings.resolution || '1K'} 
                                    onSelect={(r) => effectiveSetSettings({ ...settings, resolution: r })} 
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                />
                                <AspectRatioSelector 
                                    aspectRatio={settings.aspectRatio} 
                                    isVideo={false} 
                                    onSelect={(r) => effectiveSetSettings({ ...settings, aspectRatio: r })} 
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                    resolution={settings.resolution}
                                />
                                <StyleSelector 
                                    selectedStyleId={settings.styleId}
                                    styles={styleConfigs}
                                    onSelect={(id) => effectiveSetSettings({ ...settings, styleId: id || undefined })}
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                />
                                <CountSelector 
                                    count={settings.count} 
                                    isVideo={false} 
                                    onSelect={(c) => effectiveSetSettings({ ...settings, count: c })} 
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                />
                            </>
                        )}

                        {/* Video: Keep Resolution, Aspect Ratio, Duration, Count */}
                        {activeTab === 'video' && (
                            <>
                                <ResolutionSelector 
                                    resolution={settings.resolution} 
                                    onSelect={(r) => effectiveSetSettings({ ...settings, resolution: r })} 
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                />
                                <AspectRatioSelector 
                                    aspectRatio={settings.aspectRatio} 
                                    isVideo={true} 
                                    onSelect={(r) => effectiveSetSettings({ ...settings, aspectRatio: r })} 
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                    resolution={settings.resolution}
                                />
                                <DurationSelector 
                                    duration={settings.duration} 
                                    onSelect={(d) => effectiveSetSettings({ ...settings, duration: d })} 
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                />
                                <CountSelector 
                                    count={settings.count} 
                                    isVideo={true} 
                                    onSelect={(c) => effectiveSetSettings({ ...settings, count: c })} 
                                    selectedModelId={settings.model}
                                    models={availableModels}
                                />
                            </>
                        )}

                        {/* Audio: Keep ALL controls (Voice) */}
                        {activeTab === 'audio' && (() => {
                            const audioModel = availableModels[settings.model];
                            const voiceList = (audioModel?.voices ?? []).map((v: { id?: string; name?: string; value?: string; label?: string; gender?: string; desc?: string }) => ({
                                value: v.value ?? v.id ?? '',
                                label: v.label ?? v.name ?? v.value ?? v.id ?? '',
                                ...(v.gender != null && { gender: v.gender }),
                                ...(v.desc != null && { desc: v.desc }),
                            }));
                            return voiceList.length > 0 ? (
                                <VoiceSelector
                                    voice={settings.voice}
                                    voices={voiceList}
                                    onSelect={(v) => effectiveSetSettings({ ...settings, voice: v })}
                                />
                            ) : null;
                        })()}

                        {activeTab === 'music' && (
                            <span className="text-[10px] text-muted-foreground px-2">
                                当前模式：
                                {(settings.musicGenerateLyrics ?? false) && (settings.musicGenerateMusic ?? true)
                                  ? '歌词 -> 音乐'
                                  : (settings.musicGenerateLyrics ?? false)
                                    ? '仅歌词'
                                    : '仅音乐'}
                            </span>
                        )}
                    </div>
                </motion.div>
            )}
        </AnimatePresence>

        {/* Main Input Bar */}
        <motion.div 
            layout
            transition={{ type: "spring", bounce: 0, duration: 0.5 }}
            className={cn(
                "bg-black/40 backdrop-blur-md border border-white/10 shadow-xl relative overflow-hidden z-20 mx-auto pointer-events-auto transform-gpu",
                isExpanded ? "rounded-3xl w-[720px]" : "rounded-full hover:border-white/20 w-[580px]"
            )}
        >
          <div className={cn("w-full transition-opacity duration-200", isExpanded ? "hidden opacity-0" : "block opacity-100 h-[52px]")}>
             <CollapsedView 
                inputText={inputText} 
                activeTab={activeTab} 
                disableTabs={isEditMode}
                inputAssets={inputAssets}
                isGenerating={isGeneratingForBar}
                canGenerate={!!inputText.trim()}
                currentTaskId={isEditMode ? selectedNodeData?.taskId : undefined}
                onCancel={isEditMode && selectedNodeData?.taskId && selectedNodeId ? () => {
                    DefaultService.cancelTask(selectedNodeData!.taskId!);
                    updateNodeData({ taskId: undefined, status: 'IDLE', error: '已取消' });
                } : undefined}
                onTabChange={(tab) => {
                    if (isEditMode) return; // Lock tab in edit mode
                    setActiveTab(tab);
                    if (tab === 'text') {
                        setShowChat(true);
                    }
                    if (tab === 'image' || tab === 'video' || tab === 'audio' || tab === 'music') {
                        setIsExpanded(false);
                    }
                }}
                onInputChange={handleInputChange}
                onSubmit={handleGenerate}
                onWorkflowSubmit={handleWorkflowGenerate}
                onExpand={() => setIsExpanded(true)}
                onClearChat={handleClearChat}
                inputPlaceholder={inputPlaceholder}
                isVisible={!isExpanded}
             />
          </div>

          <div className={cn("w-full transition-opacity duration-200", isExpanded ? "block opacity-100" : "hidden opacity-0 h-0 overflow-hidden")}>
            <div className="flex flex-row w-full">
                <div className="flex-1 flex flex-col px-2.5 pb-2.5 pt-4 min-h-[100px]">
                    {/* Edit mode indicator */}
                    {isEditMode && selectedNodeData && (
                        <div className="flex items-center gap-2 mb-2 px-1">
                            <div className="flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-[10px] font-bold text-cyan-400">
                                <span className="truncate max-w-[120px]">{selectedNodeData.title}</span>
                            </div>
                            <span className="text-[10px] text-muted-foreground">编辑节点</span>
                        </div>
                    )}

                    <AutoResizeTextarea 
                        value={inputText} 
                        onChange={handleInputChange}
                        onEnter={handleGenerate}
                        isExpanded={isExpanded}
                        placeholder={inputPlaceholder}
                        inputAssets={inputAssets}
                    />
                    
                    <InputFooter 
                        isGenerating={isGeneratingForBar}
                        canGenerate={!!inputText.trim()}
                        onGenerate={handleGenerate}
                        currentTaskId={isEditMode ? selectedNodeData?.taskId : undefined}
                        onCancel={isEditMode && selectedNodeData?.taskId && selectedNodeId ? () => {
                            DefaultService.cancelTask(selectedNodeData!.taskId!);
                            updateNodeData({ taskId: undefined, status: 'IDLE', error: '已取消' });
                        } : undefined}
                        activeTab={activeTab}
                        settings={settings}
                        availableModels={availableModels}
                        lyricsModels={lyricsModels}
                        musicModels={musicModels}
                        onUpdateSettings={effectiveSetSettings}
                        isEditMode={isEditMode}
                        editNodeType={selectedNodeData?.type}
                    />
                </div>
            </div>
          </div>
        </motion.div>

      </div>
  );
};

export const InteractionInput = React.memo(InteractionInputComponent);
