import React, { useState, useEffect, useRef, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { Textarea } from '@/components/ui/textarea';
import { Card, CardContent, CardHeader } from '@/components/ui/card';
import { supabase } from '@/integrations/supabase/client';
import { toast } from 'sonner';
import { Bot, Loader2, Send, X, Maximize2, Minimize2, Pin, PinOff, Mic, MicOff, Sparkles, MessageSquare } from 'lucide-react';
import { ScrollArea } from '@/components/ui/scroll-area';
import { getSystemSchema } from '@/utils/systemSchema';
import { Badge } from '@/components/ui/badge';
import { AIAgent, AI_AGENTS } from '@/types/agents';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { cn } from '@/lib/utils';
import { SpeechRecognitionService } from '@/utils/speechRecognition';
import { 
  extractUnifiedActions, 
  executeUnifiedActions, 
  getActionLabel, 
  validateUnifiedAction,
  UnifiedAction,
} from '@/ai/unifiedActions';
import { useNavigate } from 'react-router-dom';
import { DynamicRenderer, type UISchema, type RenderContext } from '@/ai/genui';
import { subscribeToAIMessage } from '@/components/admin/aftersales/ServiceWorkbench';
import { routeAndCallGenUI, getAgentName, type GenUIAgentType } from '@/services/genUIRouter';
import { pushToWorkbench, AGENT_TO_TAB_MAP } from '@/services/workbenchEventBus';
import { Switch } from '@/components/ui/switch';
import { Label } from '@/components/ui/label';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

interface Message {
  role: 'user' | 'assistant';
  content: string;
  timestamp: Date;
  actions?: Action[];
  ui_schema?: UISchema; // Gen UI schema for dynamic rendering
}

interface Action {
  kind: 'page_action' | 'data_action' | 'legacy';
  type: string;
  params: any;
  description?: string;
  reasoning?: string;
  executed?: boolean;
  result?: string;
  error?: string;
}

// 页面状态管理 - 用于跨组件传递过滤/排序/搜索状态
export interface PageState {
  filters?: Record<string, any>;
  sort?: { field: string; direction: 'asc' | 'desc' };
  search?: string;
  displayData?: any[];
  highlightIds?: string[];
}

/** 消息体 Markdown 渲染 — 代码块、表格、列表等格式 */
function MarkdownRenderer({ content, isUser }: { content: string; isUser?: boolean }) {
  return (
    <div className={cn(
      "text-sm break-words overflow-wrap-anywhere",
      // 助手消息启用 prose 排版样式，用户消息保持简洁
      !isUser && "prose prose-sm dark:prose-invert max-w-none"
    )}>
      <ReactMarkdown remarkPlugins={[remarkGfm]}>
        {content}
      </ReactMarkdown>
    </div>
  );
}

// 创建一个简单的事件总线用于页面状态通信
const pageStateListeners: Set<(state: PageState & { tab?: string }) => void> = new Set();

export const subscribeToPageState = (callback: (state: PageState & { tab?: string }) => void) => {
  pageStateListeners.add(callback);
  return () => pageStateListeners.delete(callback);
};

export const emitPageState = (state: PageState & { tab?: string }) => {
  pageStateListeners.forEach(callback => callback(state));
};

interface AdminAIAssistantProps {
  defaultOpen?: boolean;
  defaultPinned?: boolean;
  fullscreen?: boolean;
  embedded?: boolean; // 嵌入 ResizablePanel 模式
  onNavigate?: (tab: string) => void;
  hideInput?: boolean;
}

export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({ 
  defaultOpen = false,
  defaultPinned = false,
  fullscreen = false,
  embedded = false,
  onNavigate,
  hideInput = false
}) => {
  const navigate = useNavigate();
  // 当 pinned 或 fullscreen 时，也应该认为是 open 状态
  const [isOpen, setIsOpen] = useState(defaultOpen || defaultPinned || fullscreen);
  const [isExpanded, setIsExpanded] = useState(false);
  const [isPinned, setIsPinned] = useState(defaultPinned);
  const [userMessage, setUserMessage] = useState('');
  const [messages, setMessages] = useState<Message[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [isInitialLoading, setIsInitialLoading] = useState(true);
  const [conversationId, setConversationId] = useState<string>('');
  const [adminContext, setAdminContext] = useState<any>(null);
  const [currentAgent, setCurrentAgent] = useState<AIAgent>(AI_AGENTS.manager);
  const [isRecording, setIsRecording] = useState(false);
  const [interimText, setInterimText] = useState("");
  const [useGenUI, setUseGenUI] = useState(false); // 默认使用 Coze Agent
  const [lastGenUIAgent, setLastGenUIAgent] = useState<GenUIAgentType | null>(null);
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const speechServiceRef = useRef<SpeechRecognitionService | null>(null);
  
  // 拖动相关状态
  const [position, setPosition] = useState({ x: window.innerWidth - 640, y: window.innerHeight - 600 });
  const [isDragging, setIsDragging] = useState(false);
  const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
  const cardRef = useRef<HTMLDivElement>(null);

  // Initialize speech recognition service
  useEffect(() => {
    if (!SpeechRecognitionService.isSupported()) {
      console.log('Speech recognition not supported in this browser');
      return;
    }

    speechServiceRef.current = new SpeechRecognitionService(
      // onResult - when we get final text
      (text) => {
        console.log('语音识别最终结果:', text);
        setUserMessage(prev => prev + (prev ? ' ' : '') + text);
        setInterimText("");
      },
      // onError
      (error) => {
        console.error('Speech recognition error:', error);
        toast.error(error.message);
        setIsRecording(false);
        setInterimText("");
      },
      // onEnd
      () => {
        console.log('语音识别会话结束');
        setIsRecording(false);
        setInterimText("");
      },
      // onInterim - real-time interim results
      (text) => {
        console.log('语音识别临时结果:', text);
        setInterimText(text);
      }
    );

    return () => {
      speechServiceRef.current?.stopListening();
    };
  }, []);

  const toggleRecording = useCallback(async () => {
    if (!SpeechRecognitionService.isSupported()) {
      toast.error("您的浏览器不支持语音输入，请使用 Chrome 或 Edge 浏览器");
      return;
    }

    if (!speechServiceRef.current) {
      toast.error("语音服务初始化失败");
      return;
    }

    if (isRecording) {
      speechServiceRef.current.stopListening();
      setIsRecording(false);
      setInterimText("");
      toast.success("语音输入已停止");
    } else {
      try {
        await navigator.mediaDevices.getUserMedia({ audio: true });
        speechServiceRef.current.startListening();
        setIsRecording(true);
        toast.info("开始语音输入，请说话...");
      } catch (error) {
        console.error('Microphone permission denied:', error);
        toast.error("无法访问麦克风，请允许麦克风权限");
      }
    }
  }, [isRecording]);

  const isVoiceSupported = SpeechRecognitionService.isSupported();

  // 加载历史消息 - 监听 auth 状态变化确保用户登录后加载
  useEffect(() => {
    if (!isOpen) return;

    let isMounted = true;

    const loadHistoryMessages = async (userId: string) => {
      if (!isMounted) return;
      
      setIsInitialLoading(true);
      try {
        console.log('开始加载历史消息, userId:', userId);
        
        // 按时间降序获取最近的50条，然后反转顺序显示
        const { data: historyData, error } = await supabase
          .from('admin_chat_messages')
          .select('*')
          .eq('user_id', userId)
          .order('timestamp', { ascending: false })
          .limit(50);

        if (error) {
          console.error('查询历史消息错误:', error);
          throw error;
        }

        console.log('加载到历史消息数量:', historyData?.length || 0);

        if (isMounted && historyData && historyData.length > 0) {
          // 反转顺序，让最早的消息在前面
          const loadedMessages: Message[] = historyData
            .reverse()
            .map(msg => {
              // 尝试解析可能被错误存储的 JSON 内容
              let content = msg.content;
              if (msg.role === 'assistant' && content) {
                // 检查是否是 JSON 格式的字符串（可能是完整的 API 响应）
                if (content.startsWith('{') && content.includes('"answer"')) {
                  try {
                    const parsed = JSON.parse(content);
                    // 如果解析成功且有 answer 字段，使用 answer 作为显示内容
                    if (parsed.answer) {
                      content = parsed.answer;
                      console.log('[AdminAI] Recovered answer from stored JSON response');
                    }
                  } catch {
                    // 解析失败，保留原内容
                  }
                }
              }
              return {
                role: msg.role as 'user' | 'assistant',
                content,
                timestamp: new Date(msg.timestamp),
                actions: msg.actions ? (msg.actions as unknown as Action[]) : undefined,
              };
            });
          setMessages(loadedMessages);
        }
      } catch (error) {
        console.error('加载历史消息失败:', error);
      } finally {
        if (isMounted) {
          setIsInitialLoading(false);
        }
      }
    };

    // 先尝试获取当前用户
    const initLoad = async () => {
      const { data: { session } } = await supabase.auth.getSession();
      if (session?.user) {
        loadHistoryMessages(session.user.id);
      } else {
        // 如果没有 session，等待 auth 状态变化
        console.log('等待 auth 状态...');
      }
    };

    initLoad();

    // 监听 auth 状态变化
    const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
      console.log('Auth 状态变化:', event, session?.user?.id);
      if (event === 'SIGNED_IN' && session?.user) {
        loadHistoryMessages(session.user.id);
      }
    });

    return () => {
      isMounted = false;
      subscription.unsubscribe();
    };
  }, [isOpen]);

  // 获取管理后台上下文数据
  useEffect(() => {
    const fetchAdminContext = async () => {
      if (!isOpen) return;

      try {
        // 并行执行所有查询以提高加载速度
        const [
          { data: productsData },
          { data: ordersData },
          { data: usersData },
          { data: afterSalesData },
          { data: brandsData },
          { data: categoriesData }
        ] = await Promise.all([
          supabase
            .from('products')
            .select('*')
            .order('created_at', { ascending: false })
            .limit(50),
          
          supabase
            .from('orders')
            .select(`
              *,
              profiles:user_id (display_name, phone)
            `)
            .order('created_at', { ascending: false })
            .limit(50),
          
          supabase
            .from('profiles')
            .select('*')
            .order('created_at', { ascending: false })
            .limit(50),
          
          supabase
            .from('after_sales_requests')
            .select(`
              *,
              products:product_id (name, price),
              orders:order_id (order_number)
            `)
            .order('created_at', { ascending: false })
            .limit(50),
          
          supabase
            .from('brands')
            .select('*')
            .order('display_order', { ascending: true }),
          
          supabase
            .from('categories')
            .select('*')
            .order('display_order', { ascending: true })
        ]);

        // 计算详细统计数据
        const statistics = {
          totalProducts: productsData?.length || 0,
          activeProducts: productsData?.filter(p => p.is_active).length || 0,
          lowStock: productsData?.filter(p => p.stock_quantity < 10).length || 0,
          outOfStock: productsData?.filter(p => p.stock_quantity === 0).length || 0,
          hotProducts: productsData?.filter(p => p.is_hot).length || 0,
          recommendedProducts: productsData?.filter(p => p.is_recommended).length || 0,
          
          totalOrders: ordersData?.length || 0,
          pendingOrders: ordersData?.filter(o => o.status === 'pending').length || 0,
          processingOrders: ordersData?.filter(o => o.status === 'processing').length || 0,
          shippedOrders: ordersData?.filter(o => o.status === 'shipped').length || 0,
          deliveredOrders: ordersData?.filter(o => o.status === 'delivered').length || 0,
          cancelledOrders: ordersData?.filter(o => o.status === 'cancelled').length || 0,
          
          totalUsers: usersData?.length || 0,
          adminUsers: usersData?.filter(u => u.role === 'admin').length || 0,
          regularUsers: usersData?.filter(u => u.role === 'user').length || 0,
          
          totalAfterSales: afterSalesData?.length || 0,
          pendingAfterSales: afterSalesData?.filter(a => a.status === 'pending').length || 0,
          approvedAfterSales: afterSalesData?.filter(a => a.status === 'approved').length || 0,
          rejectedAfterSales: afterSalesData?.filter(a => a.status === 'rejected').length || 0,
          
          todayOrders: ordersData?.filter(o => 
            new Date(o.created_at).toDateString() === new Date().toDateString()
          ).length || 0,
          todayRevenue: ordersData
            ?.filter(o => new Date(o.created_at).toDateString() === new Date().toDateString())
            .reduce((sum, o) => sum + Number(o.total_amount), 0) || 0,
          
          totalRevenue: ordersData?.reduce((sum, o) => sum + Number(o.total_amount), 0) || 0,
          averageOrderValue: ordersData?.length 
            ? (ordersData.reduce((sum, o) => sum + Number(o.total_amount), 0) / ordersData.length) 
            : 0,
        };

        // 生成系统架构描述
        const systemSchema = getSystemSchema({
          products: productsData || [],
          orders: ordersData || [],
          users: usersData || [],
          afterSales: afterSalesData || [],
          brands: brandsData || [],
          categories: categoriesData || [],
          statistics,
        });

        setAdminContext({
          products: productsData || [],
          orders: ordersData || [],
          users: usersData || [],
          afterSales: afterSalesData || [],
          brands: brandsData || [],
          categories: categoriesData || [],
          statistics,
          systemSchema,
        });

        console.log('管理上下文已更新:', {
          productsCount: productsData?.length,
          ordersCount: ordersData?.length,
          usersCount: usersData?.length,
          afterSalesCount: afterSalesData?.length,
          brandsCount: brandsData?.length,
          categoriesCount: categoriesData?.length,
          statistics,
        });
      } catch (error) {
        console.error('获取管理数据失败:', error);
        toast.error('数据加载失败，请刷新重试');
      }
    };

    fetchAdminContext();
  }, [isOpen]);

  useEffect(() => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [messages]);

  // Gen UI context for dynamic rendering actions
  const handleGenUIAction = useCallback((action: string, params?: Record<string, any>) => {
    console.log('[GenUI Action]', action, params);
    switch (action) {
      case 'filter_pending':
        onNavigate?.('aftersales');
        toast.info('正在筛选待处理售后');
        break;
      case 'view_all':
        onNavigate?.('aftersales');
        break;
      case 'view_detail':
        if (params?.rowId) {
          toast.info(`查看详情: ${params.rowId}`);
        }
        break;
      case 'approve':
        toast.success(`已批准: ${params?.id}`);
        break;
      case 'reject':
        toast.info(`已拒绝: ${params?.id}`);
        break;
      case 'export_report':
        toast.info('导出功能开发中');
        break;
      case 'navigate':
        if (params?.tab) {
          onNavigate?.(params.tab);
        }
        break;
      default:
        toast.info(`执行操作: ${action}`);
    }
  }, [onNavigate]);

  const genUIContext: RenderContext = {
    onAction: handleGenUIAction,
    loading: isLoading,
  };

  // 处理来自工作台的消息 - 自动发送给 AI
  const handleWorkbenchMessage = useCallback(async (message: string) => {
    console.log('[AI Assistant] Received message from workbench:', message);
    
    // ★ 生成 session_id（如果还没有），与 handleSendMessage 保持一致
    const currentSessionId = conversationId || `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
    if (!conversationId) {
      setConversationId(currentSessionId);
    }

    // 添加用户消息到对话
    const newUserMessage: Message = {
      role: 'user',
      content: message,
      timestamp: new Date()
    };
    setMessages(prev => [...prev, newUserMessage]);
    setIsLoading(true);

    try {
      const { data: { user } } = await supabase.auth.getUser();

      // 保存用户消息
      if (user) {
        await supabase.from('admin_chat_messages').insert([{
          user_id: user.id,
          role: 'user',
          content: message,
          session_id: currentSessionId,
          timestamp: newUserMessage.timestamp.toISOString(),
        }]);
      }

      // 调用 service-genui 获取动态 UI
      const { data: genUIData, error: genUIError } = await supabase.functions.invoke('service-genui', {
        body: {
          message,
          conversation_id: currentSessionId,
        },
      });

      if (genUIError) throw genUIError;

      // 关键: 工作台消息只更新工作台，聊天区不渲染完整UI
      if (genUIData?.ui_schema) {
        // 默认推送到 service 工作台（因为这是从 ServiceWorkbench 发来的消息）
        pushToWorkbench('service', genUIData.ui_schema);
      }

      // 聊天区只显示简短确认，不包含 ui_schema
      const assistantMessage: Message = {
        role: 'assistant',
        content: genUIData?.answer || '已更新工作台视图',
        timestamp: new Date(),
        // 注意: 不包含 ui_schema，避免在聊天区重复渲染
      };

      setMessages(prev => [...prev, assistantMessage]);
      
      if (genUIData?.conversation_id) {
        setConversationId(genUIData.conversation_id);
      }

      // 保存助手消息
      if (user) {
        await supabase.from('admin_chat_messages').insert([{
          user_id: user.id,
          role: 'assistant',
          content: assistantMessage.content,
          session_id: currentSessionId,
          timestamp: assistantMessage.timestamp.toISOString(),
        }]);
      }
    } catch (error) {
      console.error('Failed to process workbench message:', error);
      toast.error('处理请求失败');
    } finally {
      setIsLoading(false);
    }
  }, [conversationId]);

  // 监听来自工作台的消息
  useEffect(() => {
    const unsubscribe = subscribeToAIMessage((message) => {
      handleWorkbenchMessage(message);
    });
    return () => { unsubscribe(); };
  }, [handleWorkbenchMessage]);

  // 用于存储待发送的外部消息
  const pendingExternalMessageRef = useRef<string | null>(null);

  // 监听来自 Manus 入口页的消息
  useEffect(() => {
    const handleManusMessage = (event: CustomEvent<string>) => {
      const message = event.detail;
      if (message) {
        pendingExternalMessageRef.current = message;
        setUserMessage(message);
      }
    };
    
    window.addEventListener('admin-ai-send', handleManusMessage as EventListener);
    return () => {
      window.removeEventListener('admin-ai-send', handleManusMessage as EventListener);
    };
  }, []);

  // 当 userMessage 被外部设置后，自动触发发送
  useEffect(() => {
    if (pendingExternalMessageRef.current && userMessage === pendingExternalMessageRef.current && !isLoading) {
      pendingExternalMessageRef.current = null;
      // 使用 setTimeout 确保 React 状态更新完成
      const timer = setTimeout(() => {
        const sendBtn = document.querySelector('[data-ai-send-btn]') as HTMLButtonElement;
        if (sendBtn && !sendBtn.disabled) {
          sendBtn.click();
        }
      }, 50);
      return () => clearTimeout(timer);
    }
  }, [userMessage, isLoading]);

  // 流式调用处理函数
  const handleStreamResponse = async (
    functionName: string,
    requestBody: any,
    onContent: (content: string) => void,
    onMeta?: (meta: any) => void,
    onDone?: (data: any) => void
  ) => {
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) throw new Error('未登录');

    const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
    const response = await fetch(`${supabaseUrl}/functions/v1/${functionName}`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${session.access_token}`,
        'Content-Type': 'application/json',
        'apikey': import.meta.env.VITE_SUPABASE_ANON_KEY,
      },
      body: JSON.stringify({ ...requestBody, stream: true }),
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(errorText);
    }

    const reader = response.body?.getReader();
    if (!reader) throw new Error('No response body');

    const decoder = new TextDecoder();
    let buffer = '';

    const processLine = (line: string) => {
      const trimmed = line.trim();
      if (!trimmed || !trimmed.startsWith('data: ')) return;

      try {
        const json = JSON.parse(trimmed.slice(6));
        if (json.type === 'text' && typeof json.content === 'string') {
          onContent(json.content);
        } else if (json.type === 'content' && json.data) {
          // 兼容旧格式
          onContent(json.data);
        } else if (json.type === 'meta' && json.data) {
          onMeta?.(json.data);
        } else if (json.type === 'done') {
          // 新格式：done 帧直接包含所有字段
          onDone?.(json);
        } else if (json.type === 'error') {
          throw new Error(json.message || 'Stream error');
        }
      } catch (e) {
        if (e instanceof SyntaxError) return;
        throw e;
      }
    };

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split('\n');
      buffer = lines.pop() || '';

      for (const line of lines) {
        processLine(line);
      }
    }

    // 处理剩余的buffer内容
    if (buffer.trim()) {
      processLine(buffer);
    }
  };

  const handleSendMessage = async () => {
    if (!userMessage.trim()) {
      toast.error('请输入消息');
      return;
    }

    // ★ 在发送前生成 session_id，确保用户消息和助手消息都用同一个 ID 存入数据库
    const currentSessionId = conversationId || `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
    if (!conversationId) {
      setConversationId(currentSessionId);
    }

    const messageToSend = userMessage;
    const newUserMessage: Message = {
      role: 'user',
      content: messageToSend,
      timestamp: new Date()
    };

    setMessages(prev => [...prev, newUserMessage]);
    setUserMessage('');
    setIsLoading(true);

    // 先添加一个空的助手消息，用于流式更新
    const assistantMessageId = Date.now().toString();
    const initialAssistantMessage: Message = {
      role: 'assistant',
      content: '',
      timestamp: new Date()
    };
    setMessages(prev => [...prev, initialAssistantMessage]);

    try {
      const { data: { user } } = await supabase.auth.getUser();

      // 保存用户消息到数据库
      if (user) {
        await supabase.from('admin_chat_messages').insert([{
          user_id: user.id,
          role: 'user',
          content: newUserMessage.content,
          session_id: currentSessionId,
          timestamp: newUserMessage.timestamp.toISOString(),
        }]);
      }

      // GenUI 模式：使用意图路由调用对应的 GenUI Edge Function
      if (useGenUI) {
        console.log('[AdminAI] Using GenUI mode');

        const genUIResponse = await routeAndCallGenUI(messageToSend, {
          conversation_id: currentSessionId,
          current_page: 'admin',
        });

        // 记录使用的 Agent
        setLastGenUIAgent(genUIResponse.agentType);

        // 自动导航到对应的工作台 Tab（不依赖 ui_schema）
        const targetTab = AGENT_TO_TAB_MAP[genUIResponse.agentType];
        if (targetTab && onNavigate) {
          console.log(`[AdminAI] Auto-navigating to ${targetTab} for agent ${genUIResponse.agentType}`);
          onNavigate(targetTab);
        }

        // 推送 UI Schema 到对应的工作台（不在聊天框中重复显示）
        if (genUIResponse.ui_schema) {
          pushToWorkbench(genUIResponse.agentType, genUIResponse.ui_schema as UISchema);
        }

        // 更新助手消息 - 只显示文字回复，不包含 ui_schema（已推送到工作台）
        setMessages(prev => prev.map((msg, idx) => 
          idx === prev.length - 1 
            ? { 
                ...msg, 
                content: genUIResponse.answer || '已更新工作台视图',
                // 不设置 ui_schema，避免在聊天框重复渲染
              }
            : msg
        ));
        
        if (genUIResponse.conversation_id) {
          setConversationId(genUIResponse.conversation_id);
        }

        // 保存到数据库
        if (user) {
          await supabase.from('admin_chat_messages').insert([{
            user_id: user.id,
            role: 'assistant',
            content: genUIResponse.answer || '',
            session_id: currentSessionId,
            timestamp: new Date().toISOString(),
          }]);
        }

        // 显示使用的 Agent 信息
        toast.success(`${getAgentName(genUIResponse.agentType)} 已响应`, {
          duration: 2000,
        });
        
        setIsLoading(false);
        return;
      }
      
      // Coze 模式：流式调用 coze-langchain，实时显示文字 + 最终渲染 ui_schema
      console.log('[AdminAI] Using Coze mode (streaming unified API)');

      let streamedAnswer = '';
      let streamedUISchema: any = null;
      let streamedUISchemaText = '';  // ui_schema 的 Markdown 表达，用于拼接到 DB content
      let streamedSessionId = '';
      let streamedAgentType: GenUIAgentType = 'manager';

      await handleStreamResponse(
        'coze-langchain',
        { text: messageToSend, session_id: currentSessionId },
        // onContent: 增量文本到达时实时更新聊天框
        (content) => {
          streamedAnswer += content;
          setMessages(prev => prev.map((msg, idx) =>
            idx === prev.length - 1
              ? { ...msg, content: streamedAnswer }
              : msg
          ));
        },
        // onMeta: 不使用
        undefined,
        // onDone: 流结束，拿到结构化数据
        (doneData: any) => {
          // streamedAnswer 是流式累积的完整纯文本，优先保留
          streamedAnswer = streamedAnswer || doneData.answer;
          streamedUISchema = doneData.ui_schema || null;
          streamedUISchemaText = doneData.ui_schema_text || '';
          streamedSessionId = doneData.session_id || '';
          streamedAgentType = (doneData.agent_type as GenUIAgentType) || 'manager';
        }
      );

      // 最终更新消息内容（包含 ui_schema 以在聊天框内渲染组件）
      setMessages(prev => prev.map((msg, idx) =>
        idx === prev.length - 1
          ? { ...msg, content: streamedAnswer || '已更新工作台视图', ui_schema: streamedUISchema }
          : msg
      ));

      console.log(`[AdminAI] Stream complete - agent: ${streamedAgentType}, has ui_schema: ${!!streamedUISchema}, answer length: ${streamedAnswer.length}`);

      // 自动导航到对应的工作台 Tab
      const targetTab = AGENT_TO_TAB_MAP[streamedAgentType];
      if (targetTab && onNavigate) {
        console.log(`[AdminAI] Auto-navigating to ${targetTab} for agent ${streamedAgentType}`);
        onNavigate(targetTab);
      }

      // 推送 UI Schema 到对应的工作台
      if (streamedUISchema) {
        pushToWorkbench(streamedAgentType, streamedUISchema as UISchema);
      }

      if (streamedSessionId) {
        setConversationId(streamedSessionId);
      }

      // 保存到数据库：content = 纯文本回答 + ui_schema 的 Markdown 表达（确保历史消息可读）
      const dbContent = (streamedAnswer || '') + (streamedUISchemaText ? '\n\n' + streamedUISchemaText : '');
      if (user) {
        await supabase.from('admin_chat_messages').insert([{
          user_id: user.id,
          role: 'assistant',
          content: dbContent,
          session_id: currentSessionId,
          timestamp: new Date().toISOString(),
        }]);
      }

      // 显示使用的 Agent 信息
      toast.success(`${getAgentName(streamedAgentType)} 已响应`, {
        duration: 2000,
      });
    } catch (error) {
      console.error('AI助理错误:', error);
      
      let errorText = '抱歉，我遇到了一些问题，请稍后再试。';
      
      if (error?.message?.includes('Workflow not published')) {
        errorText = '管理助理尚未配置完成，请联系管理员在Dify平台发布工作流。';
        toast.error('Dify工作流未发布');
      } else if (error?.message?.includes('401') || error?.message?.includes('403')) {
        errorText = 'API认证失败，请检查DIFY_API_ADMIN_KEY配置。';
        toast.error('认证失败');
      } else {
        toast.error('发送消息失败，请重试');
      }
      
      // 更新最后一条消息为错误消息
      setMessages(prev => prev.map((msg, idx) => 
        idx === prev.length - 1 
          ? { ...msg, content: errorText }
          : msg
      ));
    } finally {
      setIsLoading(false);
    }
  };

  // 执行 AI 返回的操作指令
  const executeActions = async (actions: Action[]): Promise<Action[]> => {
    const executedActions: Action[] = [];

    for (const action of actions) {
      try {
        let result = '';
        let executed = false;

        switch (action.type) {
          case 'navigate':
            // 导航到指定页面
            if (action.params.tab) {
              onNavigate?.(action.params.tab);
              executed = true;
              result = `已导航到${action.params.tab}页面`;
              toast.success(result);
            } else if (action.params.path) {
              navigate(action.params.path);
              executed = true;
              result = `已导航到${action.params.path}`;
              toast.success(result);
            }
            break;

          case 'create_product':
            // 创建新商品
            if (action.params) {
              const productData = {
                name: action.params.name || '新商品',
                price: action.params.price || 0,
                brand: action.params.brand || null,
                category: action.params.category || null,
                description: action.params.description || null,
                stock_quantity: action.params.stock_quantity || 0,
                is_active: action.params.is_active ?? true,
                is_hot: action.params.is_hot ?? false,
                is_recommended: action.params.is_recommended ?? false,
                specifications: action.params.specifications || {},
              };
              
              const { data: newProduct, error } = await supabase
                .from('products')
                .insert([productData])
                .select()
                .single();
              
              if (!error && newProduct) {
                executed = true;
                result = `商品"${newProduct.name}"创建成功，ID: ${newProduct.id}`;
                toast.success(result);
                // 导航到商品编辑页面
                navigate(`/admin/products/${newProduct.id}`);
              } else {
                result = `创建商品失败: ${error?.message}`;
                toast.error(result);
              }
            }
            break;

          case 'create_coupon':
            // 创建新优惠券
            if (action.params) {
              const couponData = {
                name: action.params.name || '新优惠券',
                code: action.params.code || `COUPON${Date.now()}`,
                type: action.params.type || 'percentage',
                discount_value: action.params.discount_value || 10,
                min_purchase_amount: action.params.min_purchase_amount || 0,
                max_discount_amount: action.params.max_discount_amount || null,
                start_date: action.params.start_date || new Date().toISOString(),
                end_date: action.params.end_date || new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
                total_quantity: action.params.total_quantity || 100,
                per_user_limit: action.params.per_user_limit || 1,
                status: 'active',
                scope: action.params.scope || 'all',
              };
              
              const { data: newCoupon, error } = await supabase
                .from('coupons')
                .insert([couponData])
                .select()
                .single();
              
              if (!error && newCoupon) {
                executed = true;
                result = `优惠券"${newCoupon.name}"创建成功，代码: ${newCoupon.code}`;
                toast.success(result);
                // 导航到优惠券编辑页面
                navigate(`/admin/coupons/${newCoupon.id}`);
              } else {
                result = `创建优惠券失败: ${error?.message}`;
                toast.error(result);
              }
            }
            break;

          case 'create_banner':
            // 创建新Banner
            if (action.params) {
              const bannerData = {
                title: action.params.title || '新Banner',
                subtitle: action.params.subtitle || null,
                button_text: action.params.button_text || null,
                link_url: action.params.link_url || null,
                image_url: action.params.image_url || null,
                display_order: action.params.display_order || 0,
                is_active: action.params.is_active ?? true,
              };
              
              const { data: newBanner, error } = await supabase
                .from('banners')
                .insert([bannerData])
                .select()
                .single();
              
              if (!error && newBanner) {
                executed = true;
                result = `Banner"${newBanner.title}"创建成功`;
                toast.success(result);
                onNavigate?.('banners');
              } else {
                result = `创建Banner失败: ${error?.message}`;
                toast.error(result);
              }
            }
            break;

          case 'create_category':
            // 创建新分类
            if (action.params) {
              const categoryData = {
                name: action.params.name || '新分类',
                description: action.params.description || null,
                parent_id: action.params.parent_id || null,
                display_order: action.params.display_order || 0,
                is_active: action.params.is_active ?? true,
              };
              
              const { data: newCategory, error } = await supabase
                .from('categories')
                .insert([categoryData])
                .select()
                .single();
              
              if (!error && newCategory) {
                executed = true;
                result = `分类"${newCategory.name}"创建成功`;
                toast.success(result);
                onNavigate?.('categories');
              } else {
                result = `创建分类失败: ${error?.message}`;
                toast.error(result);
              }
            }
            break;

          case 'create_brand':
            // 创建新品牌
            if (action.params) {
              const brandData = {
                name: action.params.name || '新品牌',
                description: action.params.description || null,
                logo_url: action.params.logo_url || null,
                display_order: action.params.display_order || 0,
                is_active: action.params.is_active ?? true,
              };
              
              const { data: newBrand, error } = await supabase
                .from('brands')
                .insert([brandData])
                .select()
                .single();
              
              if (!error && newBrand) {
                executed = true;
                result = `品牌"${newBrand.name}"创建成功`;
                toast.success(result);
                onNavigate?.('brands');
              } else {
                result = `创建品牌失败: ${error?.message}`;
                toast.error(result);
              }
            }
            break;

          case 'update_order':
            if (action.params.order_id && action.params.status) {
              const { error } = await supabase
                .from('orders')
                .update({ status: action.params.status })
                .eq('id', action.params.order_id);
              
              if (!error) {
                executed = true;
                result = `订单 ${action.params.order_id} 状态已更新为 ${action.params.status}`;
                toast.success(result);
              } else {
                result = `更新订单失败: ${error.message}`;
                toast.error(result);
              }
            }
            break;

          case 'update_product':
            if (action.params.product_id) {
              const updateData: any = {};
              if (action.params.price !== undefined) updateData.price = action.params.price;
              if (action.params.stock !== undefined) updateData.stock_quantity = action.params.stock;
              if (action.params.is_active !== undefined) updateData.is_active = action.params.is_active;
              if (action.params.is_hot !== undefined) updateData.is_hot = action.params.is_hot;
              if (action.params.is_recommended !== undefined) updateData.is_recommended = action.params.is_recommended;

              const { error } = await supabase
                .from('products')
                .update(updateData)
                .eq('id', action.params.product_id);
              
              if (!error) {
                executed = true;
                result = `商品已更新`;
                toast.success(result);
              } else {
                result = `更新商品失败: ${error.message}`;
                toast.error(result);
              }
            }
            break;

          case 'update_user':
            if (action.params.user_id && action.params.role) {
              const { error } = await supabase
                .from('profiles')
                .update({ role: action.params.role })
                .eq('user_id', action.params.user_id);
              
              if (!error) {
                executed = true;
                result = `用户角色已更新`;
                toast.success(result);
              } else {
                result = `更新用户失败: ${error.message}`;
                toast.error(result);
              }
            }
            break;

          case 'query_data':
            executed = true;
            result = '数据查询已完成';
            break;

          case 'notification':
            if (action.params.message) {
              toast.info(action.params.message);
              executed = true;
              result = '通知已发送';
            }
            break;

          case 'analysis':
            // 数据分析操作
            executed = true;
            result = `分析完成：${action.description || '数据分析'}`;
            console.log('分析结果:', action.params);
            break;

          case 'batch_update':
            // 批量更新操作
            const batchResults = [];
            for (const item of action.params.items || []) {
              try {
                const { error: batchError } = await supabase
                  .from(action.params.table)
                  .update(item.updates)
                  .eq('id', item.id);
                
                if (batchError) throw batchError;
                batchResults.push(`成功: ${item.id}`);
              } catch (err) {
                batchResults.push(`失败: ${item.id}`);
              }
            }
            executed = true;
            result = `批量更新完成：${batchResults.length} 项`;
            break;

          case 'filter':
            // 过滤页面数据
            if (action.params.tab) {
              onNavigate?.(action.params.tab);
            }
            emitPageState({
              tab: action.params.tab,
              filters: action.params.filters || {},
            });
            executed = true;
            result = `已应用过滤条件: ${JSON.stringify(action.params.filters)}`;
            toast.success('过滤条件已应用');
            break;

          case 'sort':
            // 排序页面数据
            if (action.params.tab) {
              onNavigate?.(action.params.tab);
            }
            emitPageState({
              tab: action.params.tab,
              sort: {
                field: action.params.field || 'created_at',
                direction: action.params.direction || 'desc',
              },
            });
            executed = true;
            result = `已按 ${action.params.field} ${action.params.direction === 'asc' ? '升序' : '降序'} 排序`;
            toast.success(result);
            break;

          case 'search':
            // 搜索页面数据
            if (action.params.tab) {
              onNavigate?.(action.params.tab);
            }
            emitPageState({
              tab: action.params.tab,
              search: action.params.keyword || '',
            });
            executed = true;
            result = `已搜索: "${action.params.keyword}"`;
            toast.success(result);
            break;

          case 'display_data':
            // 在页面中高亮/显示特定数据
            if (action.params.tab) {
              onNavigate?.(action.params.tab);
            }
            emitPageState({
              tab: action.params.tab,
              displayData: action.params.data || [],
              highlightIds: action.params.ids || [],
            });
            executed = true;
            result = `已显示 ${action.params.ids?.length || action.params.data?.length || 0} 条数据`;
            toast.success(result);
            break;

          case 'set_page_state':
            // 综合设置页面状态（可同时设置多个参数）
            if (action.params.tab) {
              onNavigate?.(action.params.tab);
            }
            emitPageState({
              tab: action.params.tab,
              filters: action.params.filters,
              sort: action.params.sort,
              search: action.params.search,
              displayData: action.params.displayData,
              highlightIds: action.params.highlightIds,
            });
            executed = true;
            result = '页面状态已更新';
            toast.success(result);
            break;

          default:
            result = '未知操作类型';
        }

        executedActions.push({
          ...action,
          executed,
          result,
        });
      } catch (error) {
        console.error('执行操作失败:', error);
        executedActions.push({
          ...action,
          executed: false,
          error: `执行失败: ${error instanceof Error ? error.message : '未知错误'}`,
        });
      }
    }

    return executedActions;
  };

  const handleKeyPress = (e: React.KeyboardEvent) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      handleSendMessage();
    }
  };

  // 拖动处理函数
  const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
    if (cardRef.current) {
      const rect = cardRef.current.getBoundingClientRect();
      setDragOffset({
        x: e.clientX - rect.left,
        y: e.clientY - rect.top
      });
      setIsDragging(true);
    }
  };

  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (isDragging) {
        const newX = e.clientX - dragOffset.x;
        const newY = e.clientY - dragOffset.y;
        
        // 限制在窗口范围内
        const maxX = window.innerWidth - (isExpanded ? 600 : 400);
        const maxY = window.innerHeight - (isExpanded ? 700 : 500);
        
        setPosition({
          x: Math.max(0, Math.min(newX, maxX)),
          y: Math.max(0, Math.min(newY, maxY))
        });
      }
    };

    const handleMouseUp = () => {
      setIsDragging(false);
    };

    if (isDragging) {
      document.addEventListener('mousemove', handleMouseMove);
      document.addEventListener('mouseup', handleMouseUp);
    }

    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, [isDragging, dragOffset, isExpanded]);

  // 嵌入式模式 - 直接渲染内容，由父组件 ResizablePanel 控制尺寸
  if (embedded) {
    return (
      <div className="h-full flex flex-col bg-card border-l overflow-hidden">
        <div className="flex-1 flex flex-col overflow-hidden p-3">
          <ScrollArea className="flex-1 pr-2 mb-3">
            <div className="space-y-3">
              {isInitialLoading ? (
                <div className="text-center text-muted-foreground py-8">
                  <Loader2 className="h-10 w-10 mx-auto mb-3 opacity-50 animate-spin" />
                  <p className="text-sm">加载中...</p>
                </div>
              ) : messages.length === 0 ? (
                <div className="text-center text-muted-foreground py-8">
                  <Bot className="h-10 w-10 mx-auto mb-3 opacity-20" />
                  <p className="text-sm">你好！我是AI管理助理</p>
                  <p className="text-xs mt-1">输入指令，我会自动识别意图并执行</p>
                </div>
              ) : null}
              
              {messages.map((msg, idx) => (
                <div
                  key={idx}
                  className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
                >
                  <div
                    className={cn(
                      'rounded-2xl px-3.5 py-2.5 overflow-hidden shadow-xs',
                      msg.role === 'user'
                        ? 'max-w-[85%] bg-primary text-primary-foreground'
                        : msg.ui_schema
                          ? 'w-full'
                          : 'max-w-[85%] bg-muted/60 text-foreground border border-border/40'
                    )}
                  >
                    <MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} />
                    
                    {msg.ui_schema && msg.role === 'assistant' && (
                      <div className="mt-2 pt-2 border-t border-border/50">
                        <DynamicRenderer
                          schema={msg.ui_schema}
                          context={genUIContext}
                          className="w-full"
                        />
                      </div>
                    )}
                    
                    {msg.actions && msg.actions.length > 0 && (
                      <div className="mt-2 pt-2 border-t border-border/50">
                        <p className="text-xs font-medium mb-1">执行的操作:</p>
                        {msg.actions.map((action, actionIdx) => (
                          <div 
                            key={actionIdx} 
                            className={`text-xs p-1.5 rounded mb-1 ${
                              action.error 
                                ? 'bg-destructive/10 text-destructive' 
                                : action.executed
                                  ? 'bg-green-500/10 text-green-700 dark:text-green-300' 
                                  : 'bg-muted'
                            }`}
                          >
                            <Badge 
                              variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
                              className="text-xs"
                            >
                              {action.type}
                            </Badge>
                            {action.result && (
                              <p className="text-xs mt-1">{action.executed ? `✅ ${action.result}` : action.result}</p>
                            )}
                            {action.error && (
                              <p className="text-xs mt-1 text-destructive">❌ {action.error}</p>
                            )}
                          </div>
                        ))}
                      </div>
                    )}
                    
                    <p className="text-xs mt-1 opacity-70">
                      {msg.timestamp.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })}
                    </p>
                  </div>
                </div>
              ))}
              
              {isLoading && (
                <div className="flex justify-start">
                  <div className="bg-muted rounded-lg px-3 py-2">
                    <Loader2 className="h-4 w-4 animate-spin" />
                  </div>
                </div>
              )}
              
              <div ref={messagesEndRef} />
            </div>
          </ScrollArea>

          {!hideInput && (
            <div className="flex-shrink-0 space-y-2">
              {interimText && (
                <div className="px-2 py-1 bg-primary/10 border border-primary/20 rounded-lg text-sm text-primary animate-pulse">
                  {interimText}
                </div>
              )}
              
              {isRecording && (
                <div className="flex items-center gap-2 text-xs text-destructive">
                  <span className="relative flex h-2 w-2">
                    <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-destructive opacity-75"></span>
                    <span className="relative inline-flex rounded-full h-2 w-2 bg-destructive"></span>
                  </span>
                  正在录音...
                </div>
              )}
              
              <div className="flex gap-2">
                <Textarea
                  value={userMessage}
                  onChange={(e) => setUserMessage(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' && !e.shiftKey) {
                      e.preventDefault();
                      handleSendMessage();
                    }
                  }}
                  placeholder={isRecording ? "正在聆听..." : "输入消息... (Shift+Enter换行)"}
                  className="min-h-[50px] max-h-[100px]"
                  disabled={isLoading}
                />
                <div className="flex flex-col gap-1">
                  <Button
                    onClick={toggleRecording}
                    disabled={isLoading || !isVoiceSupported}
                    variant="outline"
                    size="icon"
                    className={cn(
                      "h-[24px] w-[50px] shrink-0 transition-all",
                      isRecording && "bg-destructive/10 text-destructive border-destructive/50",
                      !isVoiceSupported && "opacity-50 cursor-not-allowed"
                    )}
                  >
                    {isRecording ? <MicOff className="h-3.5 w-3.5 animate-pulse" /> : <Mic className="h-3.5 w-3.5" />}
                  </Button>
                  <Button
                    onClick={handleSendMessage}
                    disabled={isLoading || !userMessage.trim()}
                    size="icon"
                    className="h-[24px] w-[50px] shrink-0"
                    data-ai-send-btn
                  >
                    {isLoading ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Send className="h-3.5 w-3.5" />}
                  </Button>
                </div>
              </div>
            </div>
          )}
        </div>
      </div>
    );
  }

  if (!isOpen && !isPinned && !fullscreen) {
    return (
      <Button
        onClick={() => setIsOpen(true)}
        className="fixed bottom-6 right-6 rounded-full w-14 h-14 shadow-lg z-50"
        size="icon"
      >
        <Bot className="h-6 w-6" />
      </Button>
    );
  }

  // 全屏模式 (首页专用)
  if (fullscreen) {
    return (
      <div className="w-full h-full flex flex-col bg-card overflow-hidden">

        <div className="flex-1 flex flex-col overflow-hidden p-6">
          <ScrollArea className="flex-1 pr-4 mb-4">
            <div className="space-y-4">
              {isInitialLoading ? (
                <div className="text-center text-muted-foreground py-12">
                  <Loader2 className="h-16 w-16 mx-auto mb-4 opacity-50 animate-spin" />
                  <p className="text-lg font-medium">加载中...</p>
                </div>
              ) : messages.length === 0 ? (
                <div className="text-center text-muted-foreground py-12">
                  <Bot className="h-16 w-16 mx-auto mb-4 opacity-20" />
                  <p className="text-lg font-medium">你好！我是AI管理助理</p>
                  <p className="text-sm mt-2">我可以帮你查询数据、分析订单、管理商品等</p>
                </div>
              ) : null}
              
              {messages.map((msg, idx) => (
                <div
                  key={idx}
                  className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
                >
                  <div
                    className={cn(
                      'rounded-2xl px-4 py-3 overflow-hidden shadow-xs',
                      msg.role === 'user'
                        ? 'max-w-[85%] bg-primary text-primary-foreground'
                        : 'max-w-[85%] bg-muted/60 text-foreground border border-border/40'
                    )}
                  >
                    <MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} />

                    {/* Gen UI Dynamic Rendering */}
                    {msg.ui_schema && msg.role === 'assistant' && (
                      <div className="mt-3 pt-3 border-t border-border/50">
                        <DynamicRenderer
                          schema={msg.ui_schema}
                          context={genUIContext}
                          className="w-full"
                        />
                      </div>
                    )}

                    {msg.actions && msg.actions.length > 0 && (
                      <div className="mt-2 pt-2 border-t border-border/50">
                        <p className="text-xs font-medium mb-1">执行的操作:</p>
                        {msg.actions.map((action, actionIdx) => (
                          <div
                            key={actionIdx}
                            className={`text-xs p-2 rounded mb-1 ${
                              action.error
                                ? 'bg-destructive/10 text-destructive'
                                : action.executed
                                  ? 'bg-green-500/10 text-green-700 dark:text-green-300'
                                  : 'bg-muted'
                            }`}
                          >
                            <div className="flex items-center gap-2 mb-1">
                              <Badge
                                variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
                                className="text-xs"
                              >
                                {action.type}
                              </Badge>
                              {action.description && (
                                <span className="text-xs">{action.description}</span>
                              )}
                            </div>
                            {action.reasoning && (
                              <p className="text-xs opacity-75 mb-1">{action.reasoning}</p>
                            )}
                            {action.result && (
                              <p className="text-xs font-medium">{action.result}</p>
                            )}
                            {action.error && (
                              <p className="text-xs font-medium text-destructive">{action.error}</p>
                            )}
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                </div>
              ))}

              {isLoading && (
                <div className="flex justify-start">
                  <div className="bg-muted rounded-lg px-4 py-3">
                    <Loader2 className="h-4 w-4 animate-spin" />
                  </div>
                </div>
              )}

              <div ref={messagesEndRef} />
            </div>
          </ScrollArea>

          <div className="space-y-2">
            {/* Interim text indicator */}
            {interimText && (
              <div className="px-3 py-1.5 bg-primary/10 border border-primary/20 rounded-lg text-sm text-primary animate-pulse">
                {interimText}
              </div>
            )}

            {/* Recording indicator */}
            {isRecording && (
              <div className="flex items-center gap-2 text-xs text-destructive">
                <span className="relative flex h-2 w-2">
                  <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-destructive opacity-75"></span>
                  <span className="relative inline-flex rounded-full h-2 w-2 bg-destructive"></span>
                </span>
                正在录音...
              </div>
            )}

            <div className="flex gap-2">
              <Textarea
                value={userMessage}
                onChange={(e) => setUserMessage(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter' && !e.shiftKey) {
                    e.preventDefault();
                    handleSendMessage();
                  }
                }}
                placeholder={isRecording ? "正在聆听..." : "输入消息..."}
                className="resize-none"
                rows={3}
              />
              <div className="flex flex-col gap-2">
                <Button
                  onClick={toggleRecording}
                  disabled={isLoading || !isVoiceSupported}
                  variant="outline"
                  size="icon"
                  title={isVoiceSupported ? (isRecording ? "停止语音" : "语音输入") : "浏览器不支持"}
                  className={cn(
                    "h-10 w-10 transition-all",
                    isRecording && "bg-destructive/10 text-destructive border-destructive/50",
                    !isVoiceSupported && "opacity-50 cursor-not-allowed"
                  )}
                >
                  {isRecording ? (
                    <MicOff className="h-4 w-4 animate-pulse" />
                  ) : (
                    <Mic className="h-4 w-4" />
                  )}
                </Button>
                <Button
                  onClick={handleSendMessage}
                  disabled={isLoading || !userMessage.trim()}
                  size="icon"
                  className="h-10 w-10"
                  data-ai-send-btn
                >
                  {isLoading ? (
                    <Loader2 className="h-4 w-4 animate-spin" />
                  ) : (
                    <Send className="h-4 w-4" />
                  )}
                </Button>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }

  // 固定侧边栏模式
  if (isPinned) {
    return (
      <aside className="w-[560px] h-full flex-shrink-0 flex flex-col bg-card border-l overflow-hidden">
        <div className="flex flex-row items-center justify-between p-2 border-b bg-card">
          <div className="flex items-center gap-2">
            <Bot className="h-4 w-4 text-primary" />
            <span className="text-xs font-medium">AI助理</span>
          </div>
          <div className="flex items-center space-x-1">
            <Button
              variant="ghost"
              size="icon"
              onClick={() => setIsPinned(false)}
              className="h-8 w-8"
              title="取消固定"
            >
              <PinOff className="h-4 w-4" />
            </Button>
            <Button
              variant="ghost"
              size="icon"
              onClick={() => {
                setIsOpen(false);
                setIsPinned(false);
                setMessages([]);
                setConversationId('');
              }}
              className="h-8 w-8"
            >
              <X className="h-4 w-4" />
            </Button>
          </div>
        </div>

        <div className="flex-1 flex flex-col overflow-hidden p-4">
          <ScrollArea className="flex-1 pr-4 mb-4">
            <div className="space-y-4">
              {isInitialLoading ? (
                <div className="text-center text-muted-foreground py-8">
                  <Loader2 className="h-12 w-12 mx-auto mb-3 opacity-50 animate-spin" />
                  <p className="text-sm">加载中...</p>
                </div>
              ) : messages.length === 0 ? (
                <div className="text-center text-muted-foreground py-8">
                  <Bot className="h-12 w-12 mx-auto mb-3 opacity-20" />
                  <p className="text-sm">你好！我是AI管理助理</p>
                  <p className="text-xs mt-1">我可以帮你查询数据、分析订单、管理商品等</p>
                </div>
              ) : null}
              
              {messages.map((msg, idx) => (
                <div
                  key={idx}
                  className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
                >
                    <div
                      className={cn(
                        'rounded-2xl px-4 py-2.5 overflow-hidden shadow-xs',
                        msg.role === 'user'
                          ? 'max-w-[85%] bg-primary text-primary-foreground'
                          : msg.ui_schema
                            ? 'w-full'
                            : 'max-w-[85%] bg-muted/60 text-foreground border border-border/40'
                      )}
                    >
                      <MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} />
                    
                    {/* Gen UI Dynamic Rendering */}
                    {msg.ui_schema && msg.role === 'assistant' && (
                      <div className="mt-3 pt-3 border-t border-border/50">
                        <DynamicRenderer
                          schema={msg.ui_schema}
                          context={genUIContext}
                          className="w-full"
                        />
                      </div>
                    )}
                    
                    {msg.actions && msg.actions.length > 0 && (
                      <div className="mt-2 pt-2 border-t border-border/50">
                        <p className="text-xs font-medium mb-1">执行的操作:</p>
                        {msg.actions.map((action, actionIdx) => (
                          <div 
                            key={actionIdx} 
                            className={`text-xs p-2 rounded mb-1 ${
                              action.error 
                                ? 'bg-destructive/10 text-destructive' 
                                : action.executed
                                  ? 'bg-green-500/10 text-green-700 dark:text-green-300' 
                                  : 'bg-muted'
                            }`}
                          >
                            <div className="flex items-center gap-2 mb-1">
                              <Badge 
                                variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
                                className="text-xs"
                              >
                                {action.type}
                              </Badge>
                              {action.executed && (
                                <Badge variant="secondary" className="text-xs">
                                  {action.error ? '失败' : '已执行'}
                                </Badge>
                              )}
                            </div>
                            <p className="font-medium">
                              {action.description || action.type}
                            </p>
                            {action.reasoning && (
                              <p className="text-xs opacity-80 mt-1">
                                💡 {action.reasoning}
                              </p>
                            )}
                            {action.executed && (
                              <p className={`text-xs mt-1 ${action.error ? 'text-destructive' : 'opacity-80'}`}>
                                {action.error ? `❌ ${action.error}` : `✅ ${action.result}`}
                              </p>
                            )}
                          </div>
                        ))}
                      </div>
                    )}
                    
                    <p className="text-xs mt-1 opacity-70">
                      {msg.timestamp.toLocaleTimeString('zh-CN', {
                        hour: '2-digit',
                        minute: '2-digit'
                      })}
                    </p>
                  </div>
                </div>
              ))}
              
              {isLoading && (
                <div className="flex justify-start">
                  <div className="bg-muted rounded-lg px-4 py-2">
                    <Loader2 className="h-4 w-4 animate-spin" />
                  </div>
                </div>
              )}
              
              <div ref={messagesEndRef} />
            </div>
          </ScrollArea>

          {!hideInput && (
            <div className="flex-shrink-0 space-y-2">
              {/* Interim text indicator */}
              {interimText && (
                <div className="px-3 py-1.5 bg-primary/10 border border-primary/20 rounded-lg text-sm text-primary animate-pulse">
                  {interimText}
                </div>
              )}
              
              {/* Recording indicator */}
              {isRecording && (
                <div className="flex items-center gap-2 text-xs text-destructive">
                  <span className="relative flex h-2 w-2">
                    <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-destructive opacity-75"></span>
                    <span className="relative inline-flex rounded-full h-2 w-2 bg-destructive"></span>
                  </span>
                  正在录音...
                </div>
              )}
              
              <div className="flex gap-2">
                <Textarea
                  value={userMessage}
                  onChange={(e) => setUserMessage(e.target.value)}
                  onKeyPress={handleKeyPress}
                  placeholder={isRecording ? "正在聆听..." : "输入消息... (Shift+Enter换行)"}
                  className="min-h-[60px] max-h-[120px]"
                  disabled={isLoading}
                />
                <div className="flex flex-col gap-1">
                  <Button
                    onClick={toggleRecording}
                    disabled={isLoading || !isVoiceSupported}
                    variant="outline"
                    size="icon"
                    title={isVoiceSupported ? (isRecording ? "停止语音" : "语音输入") : "浏览器不支持"}
                    className={cn(
                      "h-[28px] w-[60px] flex-shrink-0 transition-all",
                      isRecording && "bg-destructive/10 text-destructive border-destructive/50",
                      !isVoiceSupported && "opacity-50 cursor-not-allowed"
                    )}
                  >
                    {isRecording ? (
                      <MicOff className="h-4 w-4 animate-pulse" />
                    ) : (
                      <Mic className="h-4 w-4" />
                    )}
                  </Button>
                  <Button
                    onClick={handleSendMessage}
                    disabled={isLoading || !userMessage.trim()}
                    size="icon"
                    className="h-[28px] w-[60px] flex-shrink-0"
                    data-ai-send-btn
                  >
                    {isLoading ? (
                      <Loader2 className="h-4 w-4 animate-spin" />
                    ) : (
                      <Send className="h-4 w-4" />
                    )}
                  </Button>
                </div>
              </div>
            </div>
          )}
        </div>
      </aside>
    );
  }

  // 浮动窗口模式
  return (
    <Card
      ref={cardRef}
      className={`fixed z-50 shadow-2xl transition-all duration-300 ${
        isExpanded ? 'w-[800px] h-[700px]' : 'w-[600px] h-[550px]'
      }`}
      style={{
        left: `${position.x}px`,
        top: `${position.y}px`,
        cursor: isDragging ? 'grabbing' : 'default'
      }}
    >
      <CardHeader 
        className="flex flex-row items-center justify-between space-y-0 pb-2 pt-2 px-2 border-b cursor-grab active:cursor-grabbing"
        onMouseDown={handleMouseDown}
      >
        <div className="flex items-center gap-2">
          <Bot className="h-4 w-4 text-primary" />
          <span className="text-xs font-medium">AI助理</span>
        </div>
        <div className="flex items-center space-x-1">
          <Button
            variant="ghost"
            size="icon"
            onClick={() => {
              setIsPinned(true);
              setIsOpen(true);
            }}
            className="h-8 w-8"
            title="固定到右侧"
          >
            <Pin className="h-4 w-4" />
          </Button>
          <Button
            variant="ghost"
            size="icon"
            onClick={() => setIsExpanded(!isExpanded)}
            className="h-8 w-8"
          >
            {isExpanded ? (
              <Minimize2 className="h-4 w-4" />
            ) : (
              <Maximize2 className="h-4 w-4" />
            )}
          </Button>
          <Button
            variant="ghost"
            size="icon"
            onClick={() => {
              setIsOpen(false);
              setMessages([]);
              setConversationId('');
            }}
            className="h-8 w-8"
          >
            <X className="h-4 w-4" />
          </Button>
        </div>
      </CardHeader>

      <CardContent className="p-4 flex flex-col h-[calc(100%-5rem)]">
        <ScrollArea className="flex-1 pr-4 mb-4">
          <div className="space-y-4">
            {messages.length === 0 && (
              <div className="text-center text-muted-foreground py-8">
                <Bot className="h-12 w-12 mx-auto mb-3 opacity-20" />
                <p className="text-sm">你好！我是AI管理助理</p>
                <p className="text-xs mt-1">
                  我可以帮你查询数据、分析订单、管理商品等
                </p>
              </div>
            )}
            
            {messages.map((msg, idx) => (
              <div
                key={`${msg.role}-${msg.timestamp.getTime()}-${idx}`}
                className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
              >
                  <div
                    className={cn(
                      'rounded-2xl px-4 py-2.5 overflow-hidden shadow-xs',
                      msg.role === 'user'
                        ? 'max-w-[85%] bg-primary text-primary-foreground'
                        : msg.ui_schema
                          ? 'w-full'
                          : 'max-w-[85%] bg-muted/60 text-foreground border border-border/40'
                    )}
                  >
                    <MarkdownRenderer content={msg.content} isUser={msg.role === 'user'} />
                  
                  {/* Gen UI Dynamic Rendering */}
                  {msg.ui_schema && msg.role === 'assistant' && (
                    <div className="mt-3 pt-3 border-t border-border/50">
                      <DynamicRenderer
                        schema={msg.ui_schema}
                        context={genUIContext}
                        className="w-width"
                      />
                    </div>
                  )}
                  
                  {/* 显示执行的操作 */}
                  {msg.actions && msg.actions.length > 0 && (
                    <div className="mt-2 pt-2 border-t border-border/50">
                      <p className="text-xs font-medium mb-1">执行的操作:</p>
                      {msg.actions.map((action, actionIdx) => (
                        <div 
                          key={actionIdx} 
                          className={`text-xs p-2 rounded mb-1 ${
                            action.error 
                              ? 'bg-destructive/10 text-destructive' 
                              : action.executed
                                ? 'bg-green-500/10 text-green-700 dark:text-green-300' 
                                : 'bg-muted'
                          }`}
                        >
                          <div className="flex items-center gap-2 mb-1">
                            <Badge 
                              variant={action.executed ? (action.error ? 'destructive' : 'default') : 'outline'}
                              className="text-xs"
                            >
                              {action.type}
                            </Badge>
                            {action.executed && (
                              <Badge variant="secondary" className="text-xs">
                                {action.error ? '失败' : '已执行'}
                              </Badge>
                            )}
                          </div>
                          <p className="font-medium">
                            {action.description || action.type}
                          </p>
                          {action.reasoning && (
                            <p className="text-xs opacity-80 mt-1">
                              💡 {action.reasoning}
                            </p>
                          )}
                          {action.executed && (
                            <p className={`text-xs mt-1 ${action.error ? 'text-destructive' : 'opacity-80'}`}>
                              {action.error ? `❌ ${action.error}` : `✅ ${action.result}`}
                            </p>
                          )}
                        </div>
                      ))}
                    </div>
                  )}
                  
                  <p className="text-xs mt-1 opacity-70">
                    {msg.timestamp.toLocaleTimeString('zh-CN', {
                      hour: '2-digit',
                      minute: '2-digit'
                    })}
                  </p>
                </div>
              </div>
            ))}
            
            {isLoading && (
              <div className="flex justify-start">
                <div className="bg-muted rounded-lg px-4 py-2">
                  <Loader2 className="h-4 w-4 animate-spin" />
                </div>
              </div>
            )}
            
            <div ref={messagesEndRef} />
          </div>
        </ScrollArea>

        {!hideInput && (
          <div className="space-y-2">
            {/* Interim text indicator */}
            {interimText && (
              <div className="px-3 py-1.5 bg-primary/10 border border-primary/20 rounded-lg text-sm text-primary animate-pulse">
                {interimText}
              </div>
            )}
            
            {/* Recording indicator */}
            {isRecording && (
              <div className="flex items-center gap-2 text-xs text-destructive">
                <span className="relative flex h-2 w-2">
                  <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-destructive opacity-75"></span>
                  <span className="relative inline-flex rounded-full h-2 w-2 bg-destructive"></span>
                </span>
                正在录音...
              </div>
            )}
            
            <div className="flex gap-2">
              <Textarea
                value={userMessage}
                onChange={(e) => setUserMessage(e.target.value)}
                onKeyPress={handleKeyPress}
                placeholder={isRecording ? "正在聆听..." : "输入消息... (Shift+Enter换行)"}
                className="min-h-[60px] max-h-[120px]"
                disabled={isLoading}
              />
              <div className="flex flex-col gap-1">
                <Button
                  onClick={toggleRecording}
                  disabled={isLoading || !isVoiceSupported}
                  variant="outline"
                  size="icon"
                  title={isVoiceSupported ? (isRecording ? "停止语音" : "语音输入") : "浏览器不支持"}
                  className={cn(
                    "h-[28px] w-[60px] shrink-0 transition-all",
                    isRecording && "bg-destructive/10 text-destructive border-destructive/50",
                    !isVoiceSupported && "opacity-50 cursor-not-allowed"
                  )}
                >
                  {isRecording ? (
                    <MicOff className="h-4 w-4 animate-pulse" />
                  ) : (
                    <Mic className="h-4 w-4" />
                  )}
                </Button>
                <Button
                  onClick={handleSendMessage}
                  disabled={isLoading || !userMessage.trim()}
                  size="icon"
                  className="h-[28px] w-[60px] shrink-0"
                  data-ai-send-btn
                >
                  {isLoading ? (
                    <Loader2 className="h-4 w-4 animate-spin" />
                  ) : (
                    <Send className="h-4 w-4" />
                  )}
                </Button>
              </div>
            </div>
          </div>
        )}
      </CardContent>
    </Card>
  );
};
