/**
 * ⚠️ AI 开发边界警告 ⚠️
 * 
 * 此文件为前端代码，AI 仅负责维护前端相关内容
 * 
 * 严格禁止 AI 修改：
 * - supabase/functions/* (Edge Functions)
 * - supabase/config.toml
 * - 数据库 migrations
 * 
 * 如发现需要后端改动：
 * 1. 立即停止修改代码
 * 2. 提供诊断报告和建议
 * 3. 等待后端 AI 或人工处理
 */

import { useState, useCallback, useRef, useEffect } from "react";
import { useLocation } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { toast } from "sonner";
import { ChatSidebar } from "@/components/chat/ChatSidebar";
import { ChatMessage, Message as ChatMessageType } from "@/components/chat/ChatMessage";
import { ChatInput } from "@/components/chat/ChatInput";
import { useConversations, type Message as DBMessage } from "@/hooks/useConversations";
import { TypingIndicator } from "@/components/chat/TypingIndicator";
import { ProductCardSkeletonRow } from "@/components/chat/ProductCardSkeleton";

import { ScrollToBottomButton } from "@/components/chat/ScrollToBottomButton";
import { Header } from "@/components/layout/Header";
import { useCart } from "@/contexts/CartContext";
import { ProductDetailDialog } from "@/components/chat/ProductDetailDialog";
import { AfterSalesDetailDialog } from "@/components/chat/AfterSalesDetailDialog";
import { AfterSalesRequestDialog } from "@/components/chat/AfterSalesRequestDialog";
import { CheckoutDialog } from "@/components/cart/CheckoutDialog";
import { AIAgent, AI_AGENTS } from "@/types/agents";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/contexts/AuthContext";
import { callCozeEdge } from "@/utils/cozeClient";
import { streamDifyChat } from "@/utils/difyStreamClient";
import { queryCoupons, getWelcomeCoupons, type Coupon } from "@/utils/couponClient";
import { searchMemory, addMemory } from "@/utils/mem0Client";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";

const GUEST_ID_KEY = 'qianjiang_guest_uuid';
let _guestIdMemoryFallback: string | null = null;
let _activeConvId: string | null = null; // 模块级变量，绕过 React 闭包
function makeUUID(): string {
  try { return crypto.randomUUID(); } catch { /* 非 HTTPS 环境 */ }
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = Math.random() * 16 | 0;
    return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
  });
}
function getOrCreateGuestId(): string {
  try {
    const existing = localStorage.getItem(GUEST_ID_KEY);
    if (existing) return existing;
    const id = makeUUID();
    localStorage.setItem(GUEST_ID_KEY, id);
    return id;
  } catch {
    // 无痕浏览等场景下 localStorage 不可用，用内存兜底保证同一会话内 ID 不变
    if (!_guestIdMemoryFallback) _guestIdMemoryFallback = makeUUID();
    return _guestIdMemoryFallback;
  }
}

export default function ChatPage() {
  const location = useLocation();
  const { user } = useAuth();
  
  // 使用共享的对话管理hook
  const {
    conversations: rawConversations,
    currentConversationId: activeConversationId,
    messages: dbMessages,
    setMessages: setDbMessages,
    setCurrentConversationId: setActiveConversationId,
    fetchConversations: loadConversations,
    fetchMessages: loadMessages,
    createConversation: createNewConversation,
    updateConversation,
    updateDifyConversationId,
    deleteConversation,
    selectConversation,
    saveMessage
  } = useConversations();

  // ✅ 用 ref 同步缓存 conversation_id 映射，消除 React state 异步竞态
  const difyConvIdMapRef = useRef<Record<string, string>>({});
  // ✅ 用 ref 保持最新 activeConversationId，避免 simulateAIResponse 闭包过期
  const activeConvIdRef = useRef<string | null>(null);
  useEffect(() => { activeConvIdRef.current = activeConversationId; }, [activeConversationId]);
  // Convert conversations for sidebar (保留 dify_conversation_id)
  const conversations = rawConversations.map(conv => ({
    id: conv.id,
    title: conv.title,
    timestamp: new Date(conv.updated_at).toLocaleString('zh-CN'),
    type: 'general' as const,
    dify_conversation_id: conv.dify_conversation_id  // ✅ 保留对话ID
  }));
  
  // Local state for ChatMessageType format
  const [messages, setMessages] = useState<ChatMessageType[]>([]);
  const [isAiTyping, setIsAiTyping] = useState(false);
  const [sidebarVisible, setSidebarVisible] = useState(() =>
    typeof window !== 'undefined' ? window.innerWidth >= 768 : true
  );
  const [selectedProductId, setSelectedProductId] = useState<string | null>(null);
  const [showProductDetail, setShowProductDetail] = useState(false);
  const [selectedAfterSalesId, setSelectedAfterSalesId] = useState<string | null>(null);
  const [showAfterSalesDetail, setShowAfterSalesDetail] = useState(false);
  const [showAfterSalesRequest, setShowAfterSalesRequest] = useState(false);
  const [selectedOrderForAfterSales, setSelectedOrderForAfterSales] = useState<any>(null);
  const [currentAgent, setCurrentAgent] = useState<AIAgent>(AI_AGENTS.general);
  const [products, setProducts] = useState<any[]>([]);
  const [orders, setOrders] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [checkoutOpen, setCheckoutOpen] = useState(false);
  const [useStream, setUseStream] = useState(true);  // 流式输出开关，默认开启
  // AI 引擎模型名（从后台 ai_provider_configs.consumer_chat 加载）
  const [chatModel, setChatModel] = useState<string>('agent-default');
  const [streamingMessageId, setStreamingMessageId] = useState<string | null>(null);  // 当前流式消息ID

  // 启动时从后台读取 AI 模型配置
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const { data } = await supabase
          .from('ai_provider_configs')
          .select('model, enabled')
          .eq('purpose', 'consumer_chat')
          .maybeSingle();
        if (!cancelled && data && data.enabled !== false && data.model) {
          setChatModel(data.model);
          console.log('[ChatPage] 已加载后台模型配置:', data.model);
        }
      } catch (e) {
        console.warn('[ChatPage] 模型配置加载失败，使用默认', e);
      }
    })();
    return () => { cancelled = true; };
  }, []);
  const scrollAreaRef = useRef<HTMLDivElement>(null);
  const { addItem } = useCart();

  // 获取产品数据 - 延迟加载
  const fetchProducts = useCallback(async () => {
    console.log('fetchProducts: 开始获取产品数据');
    try {
      const { data, error } = await supabase
        .from('products')
        .select('id, name, price, image_url, category, stock_quantity, description')
        .eq('is_active', true)
        .order('created_at', { ascending: false })
        .limit(500);
      
      if (error) throw error;
      
      console.log('fetchProducts: 获取到的产品数据:', data);
      console.log('fetchProducts: 产品数量:', data?.length);
      data?.forEach(product => {
        console.log(`产品: ${product.name}, 库存: ${product.stock_quantity}`);
      });
      
      setProducts(data || []);
      return data || []; // 返回数据
    } catch (error) {
      console.error('获取产品数据失败:', error);
      return [];
    }
  }, []);

  // 获取订单数据 - 优化查询
  const fetchOrders = useCallback(async () => {
    if (!user) return;
    
    try {
      const { data: ordersData, error: ordersError } = await supabase
        .from('orders')
        .select(`
          *,
          order_items (
            id,
            quantity,
            unit_price,
            products (
              id,
              name,
              image_url
            )
          )
        `)
        .eq('user_id', user.id)
        .limit(20)
        .order('created_at', { ascending: false });
      
      if (ordersError) throw ordersError;
      
      const ordersWithItems = ordersData?.map(order => ({
        ...order,
        items: order.order_items?.map((item: any) => ({
          name: item.products?.name || '未知商品',
          quantity: item.quantity,
          price: `¥${item.unit_price}`,
          productId: item.product_id
        })) || []
      })) || [];
      
      setOrders(ordersWithItems);
    } catch (error) {
      console.error('获取订单数据失败:', error);
    }
  }, [user]);

  const resolvePickedProducts = useCallback(async (pickedIds: string[]) => {
    if (!pickedIds.length) return [];

    const validIds = pickedIds.filter((id): id is string => Boolean(id) && !id.includes('...'));
    const truncatedIds = pickedIds.filter((id): id is string => Boolean(id) && id.includes('...'));
    const allProducts: any[] = [];

    if (validIds.length > 0) {
      const { data: exactProducts, error } = await supabase
        .from('products')
        .select('id, name, price, image_url, category, stock_quantity')
        .in('id', validIds);

      if (error) {
        console.error('获取精确匹配商品失败:', error);
      } else if (exactProducts) {
        allProducts.push(...exactProducts);
      }
    }

    for (const truncatedId of truncatedIds) {
      const prefix = truncatedId.replace('...', '');
      if (!prefix) continue;

      const { data: matchedProducts, error } = await supabase
        .from('products')
        .select('id, name, price, image_url, category, stock_quantity')
        .ilike('id', `${prefix}%`)
        .limit(1);

      if (error) {
        console.error('获取前缀匹配商品失败:', error);
        continue;
      }

      const matchedProduct = matchedProducts?.[0];
      if (matchedProduct && !allProducts.some(product => product.id === matchedProduct.id)) {
        allProducts.push(matchedProduct);
      }
    }

    return pickedIds
      .map((id) => {
        const prefix = id.includes('...') ? id.replace('...', '') : null;
        return allProducts.find(product => product.id === id || (prefix && product.id.startsWith(prefix)));
      })
      .filter((product): product is NonNullable<typeof product> => Boolean(product));
  }, []);

  // Convert DB messages to Chat messages when they change
  useEffect(() => {
    const convertedMessages: ChatMessageType[] = dbMessages.map(msg => ({
      id: msg.id,
      content: msg.content,
      sender: msg.sender_type as 'user' | 'ai',
      timestamp: new Date(msg.created_at).toLocaleTimeString('zh-CN', {
        hour: '2-digit',
        minute: '2-digit'
      }),
      type: msg.message_type === 'after_sales' ? 'aftersales' : 
            msg.message_type === 'agent_intro' ? 'agent_intro' : 
            msg.message_type as ChatMessageType['type'],
      metadata: msg.metadata as any || {}
    }));
    setMessages(convertedMessages);
  }, [dbMessages]);

  // 同步 conversations 列表到 ref，保证读取永远拿到最新值
  useEffect(() => {
    const map: Record<string, string> = { ...difyConvIdMapRef.current };
    rawConversations.forEach(conv => {
      if (conv.dify_conversation_id) {
        map[conv.id] = conv.dify_conversation_id;
      }
    });
    difyConvIdMapRef.current = map;
  }, [rawConversations]);

  // Adapt shared hook methods for local usage with Message type conversion
  const saveMessageLocal = useCallback(async (message: ChatMessageType, conversationId: string) => {
    await saveMessage({
      content: message.content,
      sender_type: message.sender,
      message_type: message.type === 'aftersales' ? 'after_sales' : 
                   message.type === 'agent_intro' ? 'agent_intro' : 
                   message.type as DBMessage['message_type'],
      metadata: message.metadata
    }, conversationId);
  }, [saveMessage]);

  // AI响应处理 - 三明治架构：先查记忆 -> 问AI -> 存记忆
  const simulateAIResponse = useCallback(async (userMessage: string) => {
    setIsAiTyping(true);
    console.trace('🔍 simulateAIResponse 入口 _activeConvId=', _activeConvId);
    const activeConversationId = _activeConvId;
    try {
      // ========== Step 1: Pre-flight - 查询 Mem0 记忆 ==========
      const userId = user?.id || getOrCreateGuestId();
      console.log('🧠 [三明治] Step 1: 查询 Mem0 记忆...');
      const userContext = await searchMemory(userId, userMessage);
      console.log('🧠 [三明治] 记忆上下文:', userContext ? `${userContext.length} chars` : '(empty)');
      
      // 确保产品数据已加载
      let currentProducts = products;
      if (currentProducts.length === 0) {
        console.log('产品数据未加载，立即加载...');
        currentProducts = await fetchProducts();
      }
      
      // 检查是否有产品数据
      if (currentProducts.length === 0) {
        throw new Error('产品数据加载失败，请刷新页面重试');
      }
      
      // 准备产品目录数据
      const catalog = currentProducts.map(p => ({
        id: p.id,
        name: p.name,
        price: p.price,
        stock_quantity: p.stock_quantity,
        category: p.category,
        description: p.description
      }));
      
      const firstProduct = currentProducts[0];
      
      // ✅ 从 ref 同步读取最新 conversation_id，登录/访客统一，零延迟零竞态
      const conversationIdFromDb = activeConversationId
        ? (difyConvIdMapRef.current[activeConversationId] || '')
        : '';
      console.log('- 对话ID (from ref):', conversationIdFromDb || '(new conversation)');

      // ========== Step 2: 流式调用 AI ─────────
      if (useStream) {
        console.log('🚀 [STREAM] 使用流式输出模式, activeConversationId=', activeConversationId, 'ref=', activeConvIdRef.current);

        const streamMessageId = `ai_stream_${Date.now()}`;
        setStreamingMessageId(streamMessageId);

        // 创建初始空消息
        const streamMessage: ChatMessageType = {
          id: streamMessageId,
          content: '',
          sender: 'ai',
          timestamp: new Date().toLocaleTimeString('zh-CN', {
            hour: '2-digit',
            minute: '2-digit'
          }),
          type: 'text',
          agent: currentAgent,
          metadata: {}
        };

        setMessages(prev => [...prev, streamMessage]);

        let fullContent = '';
        let finalMetadata: any = {};

        const streamCallbacks = {
            onText: (text: string) => {
              fullContent += text;
              setMessages(prev => prev.map(msg =>
                msg.id === streamMessageId
                  ? { ...msg, content: fullContent }
                  : msg
              ));
            },
            onDone: async (data: any) => {
              console.log('✅ [STREAM] 流式响应完成:', data);

              // 🧹 清洗：移除 AI 误把协议 JSON（picks/intent）当作正文输出的内容
              fullContent = fullContent
                .replace(/```(?:json)?\s*\{[\s\S]*?"(?:picks|intent)"[\s\S]*?\}\s*```/gi, '')
                .replace(/^\s*[•\-*]?\s*\{\s*"(?:picks|intent)"[\s\S]*?\}\s*$/gim, '')
                .replace(/\{\s*"(?:picks|intent)"\s*:[\s\S]*?\}\s*$/g, '')
                .trim();

              // 🧹 清洗：移除 LLM 幻觉生成的 URL/链接（包括 Markdown 链接格式）
              const hallucinatedUrlPatterns = [
                /\[([^\]]*)\]\(https?:\/\/[^\)]+\)/gi,
                /https?:\/\/[^\s]+/gi,
              ];
              for (const p of hallucinatedUrlPatterns) {
                fullContent = fullContent.replace(p, '');
              }
              fullContent = fullContent.trim();

              if (!fullContent && !(Array.isArray(data.picks) && data.picks.length > 0)) {
                fullContent = '抱歉，目前店铺暂无符合您需求的商品。我们主要经营手机及配件，您可以试试问"推荐一款手机"~';
              }

              let messageType: ChatMessageType['type'] = 'text';
              let responseMetadata: any = {
                highlights: data.highlights || [],
                comparison: data.comparison || undefined
              };

              if (Array.isArray(data.picks) && data.picks.length > 0) {
                const pickedIds = data.picks
                  .map((p: any) => p.product_id)
                  .filter(Boolean);
                const pickedProducts = await resolvePickedProducts(pickedIds);

                if (pickedProducts.length > 0) {
                  messageType = 'products';
                  responseMetadata.productsInfo = pickedProducts.map(product => ({
                    id: product.id,
                    name: product.name,
                    price: product.price,
                    image: product.image_url || '',
                    status: product.stock_quantity > 0 ? '现货充足' : '缺货',
                    category: product.category || '未分类',
                    stock_quantity: product.stock_quantity
                  }));

                  fullContent += `\n\n为您推荐了 ${pickedProducts.length} 个商品`;
                } else {
                  console.warn('流式 picks 已返回，但未匹配到可渲染商品:', pickedIds);
                }
              } else if (data.intent === 'AFTERSALES') {
                await fetchOrders();
                if (orders.length > 0) {
                  messageType = 'order';
                  responseMetadata.orderInfo = orders.map(order => ({
                    orderId: order.order_number,
                    orderUuid: order.id,
                    status: order.status,
                    items: order.items || [],
                    total: `¥${order.total_amount}`,
                    orderDate: new Date(order.created_at).toLocaleDateString('zh-CN'),
                    shippingAddress: order.shipping_address
                  }));
                }
              }

              // ★ action 分发：LLM 指示前端执行特定操作
              if (data.action) {
                console.log('🎬 [ACTION] 触发前端操作:', data.action, data.actionPayload);
                switch (data.action) {
                  case 'show_after_sales_form': {
                    const payload = data.actionPayload || {};
                    const orderId = payload.orderId || (orders.length > 0 ? orders[0].id : '');
                    const orderNumber = payload.orderNumber || (orders.length > 0 ? orders[0].order_number : '');
                    const products = (payload.products && payload.products.length > 0)
                      ? payload.products
                      : (orders.length > 0 ? orders[0].items || [] : []);
                    if (orderId && orderNumber) {
                      setSelectedOrderForAfterSales({ id: orderId, orderNumber, products });
                      setShowAfterSalesRequest(true);
                      console.log('✅ [ACTION] 弹出 AfterSalesRequestDialog:', { orderId, orderNumber });
                    }
                    break;
                  }
                  case 'show_order_detail': {
                    await fetchOrders();
                    if (orders.length > 0) {
                      messageType = 'order';
                      responseMetadata.orderInfo = orders.map(order => ({
                        orderId: order.order_number,
                        orderUuid: order.id,
                        status: order.status,
                        items: order.items || [],
                        total: `¥${order.total_amount}`,
                        orderDate: new Date(order.created_at).toLocaleDateString('zh-CN'),
                        shippingAddress: order.shipping_address
                      }));
                    }
                    break;
                  }
                  case 'show_faq':
                    // FAQ 内容已在 LLM 回复文本中，无需额外 UI 操作
                    console.log('📚 [ACTION] FAQ 模式，内容已在回复中');
                    break;
                }
              }

              // ★ components 处理：LLM 返回的 UI 组件数组
              if (Array.isArray(data.components) && data.components.length > 0) {
                console.log('🧩 [COMPONENTS] LLM 返回组件:', data.components.length);
                for (const comp of data.components) {
                  switch (comp.type) {
                    case 'order_status_card':
                      if (!responseMetadata.orderInfo && comp.props) {
                        responseMetadata.orderInfo = [{
                          orderId: comp.props.orderNumber || '',
                          orderUuid: comp.props.orderId || '',
                          status: comp.props.status || 'unknown',
                          total: comp.props.total || '',
                          orderDate: comp.props.createdAt || '',
                        }];
                        if (messageType === 'text') messageType = 'order';
                      }
                      break;
                    case 'after_sales_progress':
                      if (!responseMetadata.afterSalesInfo && comp.props) {
                        responseMetadata.afterSalesInfo = [{
                          id: comp.props.afterSalesId || '',
                          type: comp.props.type || '',
                          status: comp.props.status || '',
                          reason: comp.props.reason || '',
                          createdAt: comp.props.createdAt || '',
                          refundAmount: comp.props.refundAmount,
                        }];
                        if (messageType === 'text') messageType = 'aftersales';
                      }
                      break;
                  }
                }
              }

              // ✅ 保存 conversation_id：先写 ref（同步、零延迟），再持久化
              if (data.conversation_id && activeConversationId) {
                difyConvIdMapRef.current[activeConversationId] = data.conversation_id;
                await updateDifyConversationId(activeConversationId, data.conversation_id);
              }

              finalMetadata = responseMetadata;

              setMessages(prev => prev.map(msg =>
                msg.id === streamMessageId
                  ? { ...msg, content: fullContent, type: messageType, metadata: responseMetadata }
                  : msg
              ));

              if (activeConversationId) {
                await saveMessageLocal({
                  id: streamMessageId,
                  content: fullContent,
                  sender: 'ai',
                  timestamp: new Date().toLocaleTimeString('zh-CN', {
                    hour: '2-digit',
                    minute: '2-digit'
                  }),
                  type: messageType,
                  agent: currentAgent,
                  metadata: responseMetadata
                }, activeConversationId);
              }

              addMemory(userId, userMessage, fullContent);

              setStreamingMessageId(null);
              setIsAiTyping(false);
            },
            onError: (error: string) => {
              console.error('❌ [STREAM] 错误:', error);
              setMessages(prev => prev.map(msg =>
                msg.id === streamMessageId
                  ? { ...msg, content: '抱歉，AI助手暂时无法回复，请稍后再试。' }
                  : msg
              ));
              setStreamingMessageId(null);
              setIsAiTyping(false);
            }
        };

        await streamDifyChat(
          {
            message: userMessage,
            userId: user?.id || getOrCreateGuestId(),
            conversationId: conversationIdFromDb,
            localConversationId: activeConversationId,  // ★ 传入本地会话ID，Edge Function 用于加载历史
            userContext: userContext,
            catalog
          },
          streamCallbacks
        );

        return;
      }

      // ========== 非流式模式 ─────────
      console.log('📤 Step 2: 非流式调用, activeConversationId=', activeConversationId, 'ref=', activeConvIdRef.current);
      const { data: intentCard, traceId, status, error: callError } = await callCozeEdge({
        message: userMessage,
        userId: user?.id || getOrCreateGuestId(),
        conversationId: conversationIdFromDb,
        localConversationId: activeConversationId,
        userContext: userContext,
        product: {
          id: firstProduct.id,
          title: firstProduct.name,
          description: firstProduct.description || '',
          price: Number(firstProduct.price)
        },
        catalog
      });

      console.log('📥 响应结果');
      console.log('- AI引擎: ai-hub');
      console.log('- trace_id:', traceId);
      console.log('- status:', status);
      console.log('- 原始 intentCard:', JSON.stringify(intentCard, null, 2));

      if (callError || !intentCard) {
        console.error('AI API调用失败:', callError);
        const errorMsg = callError || `系统繁忙，请稍后再试（追踪码：${traceId}）`;
        toast.error("AI回复失败", {
          description: errorMsg,
        });
        throw new Error(errorMsg);
      }
      
      // 尝试从 answer 字段解析完整的产品信息
      let parsedAnswer = null;
      try {
        if ((intentCard as any).answer && typeof (intentCard as any).answer === 'string') {
          parsedAnswer = JSON.parse((intentCard as any).answer);
          console.log('📊 从 answer 解析出的数据:', {
            catalog_count: parsedAnswer?.meta?.catalog_count,
            picks_count: parsedAnswer?.picks?.length,
            probe_id: parsedAnswer?.meta?.probe_id
          });
        }
      } catch (e) {
        console.error('解析 answer 失败:', e);
      }
      
      // 优先使用 parsedAnswer，如果解析失败则使用原始 intentCard
      const finalIntentCard = parsedAnswer || intentCard;
      
      // ✅ 关键修复：conversation_id 始终从原始 intentCard 获取，因为它是 Edge Function 添加的顶层字段
      // parsedAnswer 是从 answer JSON 解析的，不包含 conversation_id
      const difyReturnedConversationId = intentCard?.conversation_id;
      
      console.log('🔍 最终使用的 intentCard:', JSON.stringify(finalIntentCard, null, 2));
      console.log('🔍 picks 详细信息:', {
        picks: finalIntentCard?.picks,
        picksType: typeof finalIntentCard?.picks,
        picksIsArray: Array.isArray(finalIntentCard?.picks),
        picksLength: finalIntentCard?.picks?.length
      });
      console.log('💬 Dify conversation_id (从原始 intentCard):', difyReturnedConversationId);
      
      // ✅ 保存 conversation_id：先写 ref（同步、零延迟），再持久化（登录用 DB / 访客用 localStorage）
      if (difyReturnedConversationId && activeConversationId) {
        const isNewConversation = difyReturnedConversationId !== conversationIdFromDb;
        console.log('💾 保存会话ID:', {
          returned_id: difyReturnedConversationId,
          conv_id: activeConversationId,
          is_new: isNewConversation ? '✨ 新对话' : '📌 继续对话',
          old_id: conversationIdFromDb || '(none)'
        });
        difyConvIdMapRef.current[activeConversationId] = difyReturnedConversationId;
        await updateDifyConversationId(activeConversationId, difyReturnedConversationId);
      }

      // ✅ 生产约定：只消费顶层合同字段，不解析 answer 或 title 内的 JSON
      
      // 🔍 Debug（开发态）：显示 X-Trace-Id 和 meta 信息
      console.log('═══════════════════════════════════════');
      console.log('🔍 [Dify Debug Info]');
      console.log('═══════════════════════════════════════');
      console.log('📌 Trace ID:', traceId);
      console.log('📌 Catalog Count:', finalIntentCard.meta?.catalog_count, '(≥1 表示命中目录)');
      console.log('📌 Platform:', finalIntentCard.meta?.platform, '(应为 lovable/edge-fn/...)');
      console.log('📌 顶层合同字段:');
      console.log('  - title:', finalIntentCard.title);
      console.log('  - intent:', finalIntentCard.intent);
      console.log('  - sentiment:', finalIntentCard.sentiment);
      console.log('  - highlights:', finalIntentCard.highlights);
      console.log('  - picks:', finalIntentCard.picks);
      console.log('  - next:', finalIntentCard.next);
      console.log('  - platform:', finalIntentCard.meta?.platform);
      console.log('  - user:', finalIntentCard.meta?.user);
      if ((finalIntentCard as any).answer) {
        console.log('📌 Dify 原始回复 (answer 字段):');
        console.log((finalIntentCard as any).answer);
      }
      console.log('═══════════════════════════════════════');
      
      // 使用合同字段构建回复
      let aiContent = finalIntentCard.title || '收到您的消息';
      
      // 🔍 开发态：在回复中显示 catalog_count
      // 强制转换为数字，确保 0 值能正确处理
      const rawCatalogCount = finalIntentCard.meta?.catalog_count;
      const catalogCount = typeof rawCatalogCount === 'number' ? rawCatalogCount : (rawCatalogCount != null ? Number(rawCatalogCount) : -1);
      
      console.log('🔍 catalogCount 调试:', {
        raw: rawCatalogCount,
        type: typeof rawCatalogCount,
        converted: catalogCount,
        meta: finalIntentCard.meta
      });
      
      aiContent += `\n\n[调试信息] Catalog Count: ${catalogCount} ${catalogCount >= 1 ? '✅' : catalogCount === -1 ? '⚠️未返回' : '❌=0'}`;
      
      // 如果有 highlights，添加到回复中
      if (finalIntentCard.highlights && finalIntentCard.highlights.length > 0) {
        aiContent += '\n\n重点信息：\n' + finalIntentCard.highlights.map(h => `• ${h}`).join('\n');
      }
      
      // 如果有 picks（商品推荐），添加提示
      if (finalIntentCard.picks && finalIntentCard.picks.length > 0) {
        aiContent += '\n\n为您推荐了 ' + finalIntentCard.picks.length + ' 个商品';
      }
      
      let enhancedAiContent = aiContent;
      // 如果询问商品，在 Dify 回复后添加商品推荐提示
      if (userMessage.toLowerCase().includes('商品') || userMessage.toLowerCase().includes('产品')) {
        enhancedAiContent = aiContent + '\n\n以下是为您推荐的商品：';
      }
      
      const conversationId = activeConversationId;
      
      // 持久化conversation_id到状态中
      if (conversationId && conversationId !== activeConversationId) {
        console.log('更新会话ID:', conversationId);
        // 可以在这里将conversation_id保存到数据库或状态中
      }
      
      console.log('Dify response - trace_id:', traceId);
      console.log('Dify response - catalog_count:', finalIntentCard.meta?.catalog_count || 0);
      console.log('Dify conversation_id:', conversationId);

      // ✅ 基于 Dify 返回的 intent 来判断消息类型，而不是基于关键词
      const isShoppingIntent = finalIntentCard.intent === "SHOPPING" || (finalIntentCard.picks && finalIntentCard.picks.length > 0);
      const isAfterSalesIntent = finalIntentCard.intent === "AFTERSALES";
      
      // 保留关键词检测作为辅助判断（当 intent 为 GENERAL 时）
      const hasProductKeywords = userMessage.toLowerCase().includes('产品') || 
        userMessage.toLowerCase().includes('商品') || 
        userMessage.toLowerCase().includes('推荐') || 
        userMessage.toLowerCase().includes('买') || 
        userMessage.toLowerCase().includes('购买') ||
        userMessage.toLowerCase().includes('手机') ||
        userMessage.toLowerCase().includes('电脑') ||
        userMessage.toLowerCase().includes('耳机');

      const hasOrderKeywords = userMessage.toLowerCase().includes('订单') || 
        userMessage.toLowerCase().includes('查询') || 
        userMessage.toLowerCase().includes('物流') || 
        userMessage.toLowerCase().includes('发货') || 
        userMessage.toLowerCase().includes('快递') || 
        userMessage.toLowerCase().includes('配送');
      
      const hasCouponKeywords = userMessage.toLowerCase().includes('优惠') ||
        userMessage.toLowerCase().includes('折扣') ||
        userMessage.toLowerCase().includes('券') ||
        userMessage.toLowerCase().includes('活动');
      
      let aiResponse = enhancedAiContent;
      let messageType: ChatMessageType['type'] = "text";
      let responseMetadata: ChatMessageType['metadata'] = {};

      // 优先使用 Dify 的 intent 判断
      if (hasCouponKeywords) {
        // 查询可用优惠券
        const coupons = await queryCoupons({
          available_only: true,
          limit: 3
        });
        
        if (coupons.length > 0) {
          // 为每个优惠券创建单独的消息
          for (const coupon of coupons) {
            const couponMessage: ChatMessageType = {
              id: `ai_coupon_${Date.now()}_${coupon.id}`,
              content: `为您推荐了一张优惠券：${coupon.name}`,
              sender: "ai",
              timestamp: new Date().toLocaleTimeString('zh-CN', {
                hour: '2-digit',
                minute: '2-digit'
              }),
              type: "coupon",
              agent: currentAgent,
              metadata: {
                couponInfo: {
                  id: coupon.id,
                  code: coupon.code,
                  name: coupon.name,
                  description: coupon.description,
                  type: coupon.type,
                  discount_value: coupon.discount_value,
                  min_purchase_amount: coupon.min_purchase_amount,
                  max_discount_amount: coupon.max_discount_amount,
                  end_date: coupon.end_date,
                  scope: coupon.scope
                }
              }
            };
            
            setMessages(prev => [...prev, couponMessage]);
            if (activeConversationId) {
              await saveMessageLocal(couponMessage, activeConversationId);
            }
            
            // 添加小延迟，让消息依次出现
            await new Promise(resolve => setTimeout(resolve, 300));
          }
          
          // 返回，不再执行后续逻辑
          return;
        }
      } else if (isAfterSalesIntent || (!isShoppingIntent && hasOrderKeywords)) {
        await fetchOrders();
        if (orders.length > 0) {
          messageType = "order";
          responseMetadata = {
            ...responseMetadata,
            orderInfo: orders.map(order => ({
              orderId: order.order_number,
              orderUuid: order.id,
              status: order.status,
              items: order.items || [],
              total: `¥${order.total_amount}`,
              orderDate: new Date(order.created_at).toLocaleDateString('zh-CN'),
              shippingAddress: order.shipping_address
            }))
          };
        }
      } else if (isShoppingIntent || hasProductKeywords) {
        messageType = "products";
        
        console.log('🔍 检查 picks 条件:', {
          hasPicks: !!finalIntentCard.picks,
          picksIsArray: Array.isArray(finalIntentCard.picks),
          picksLength: finalIntentCard.picks?.length,
          picks: finalIntentCard.picks
        });
        
        let displayProducts: any[] = [];
        
        // ✅ 如果Dify返回了picks推荐，直接用picks的ID从数据库获取产品
        if (finalIntentCard.picks && Array.isArray(finalIntentCard.picks) && finalIntentCard.picks.length > 0) {
          const pickedIds = finalIntentCard.picks.map(p => p.product_id);
          console.log('📌 Dify推荐的产品ID:', pickedIds);
          
          // ✅ 分离完整ID和被截断的ID（Dify 有时会截断长UUID）
          const validIds = pickedIds.filter(id => id && !id.includes('...'));
          const truncatedIds = pickedIds.filter(id => id && id.includes('...'));
          
          console.log('🔍 有效ID:', validIds);
          console.log('⚠️ 被截断ID:', truncatedIds);
          
          // ✅ 先获取完整ID对应的产品
          let allProducts: any[] = [];
          if (validIds.length > 0) {
            const { data: pickedProducts, error } = await supabase
              .from('products')
              .select('id, name, price, image_url, category, stock_quantity, description')
              .in('id', validIds);
            
            if (error) {
              console.error('❌ 获取推荐产品失败:', error);
            } else if (pickedProducts) {
              allProducts = [...pickedProducts];
            }
          }
          
          // ✅ 对于被截断的ID，尝试用前缀匹配查找
          for (const truncatedId of truncatedIds) {
            const prefix = truncatedId.replace('...', '');
            console.log('🔍 尝试前缀匹配:', prefix);
            
            const { data: matchedProducts, error } = await supabase
              .from('products')
              .select('id, name, price, image_url, category, stock_quantity, description')
              .ilike('id', `${prefix}%`)
              .limit(1);
            
            if (!error && matchedProducts && matchedProducts.length > 0) {
              console.log('✅ 前缀匹配成功:', matchedProducts[0].name);
              allProducts.push(matchedProducts[0]);
            } else {
              console.log('⚠️ 前缀匹配失败:', prefix);
            }
          }
          
          // ✅ 按照 picks 的顺序排列产品
          if (allProducts.length > 0) {
            displayProducts = pickedIds
              .map(id => {
                // 精确匹配或前缀匹配
                const prefix = id.includes('...') ? id.replace('...', '') : null;
                return allProducts.find(p => 
                  p.id === id || (prefix && p.id.startsWith(prefix))
                );
              })
              .filter((p): p is typeof allProducts[0] => p !== undefined);
            
            console.log('✅ 最终匹配的产品:', displayProducts.map(p => ({ id: p.id, name: p.name })));
          }
        }
        
        // ✅ 如果没有picks或picks产品获取失败，回退到普通获取
        if (displayProducts.length === 0) {
          console.log('⚠️ 没有有效的 picks 数据，使用默认产品列表');
          await fetchProducts();
          displayProducts = products.slice(0, 12);
        }
        
        // 合并Dify响应的metadata和我们的产品数据
        const ourProductsInfo = displayProducts.map(product => ({
          id: product.id,
          name: product.name,
          price: product.price,
          image: product.image_url || "",
          status: product.stock_quantity > 0 ? "现货充足" : "缺货",
          category: product.category || "未分类",
          stock_quantity: product.stock_quantity
        }));
        
        console.log('✅ 最终展示的产品数量:', ourProductsInfo.length);
        console.log('✅ 最终展示的产品:', ourProductsInfo.map(p => p.name));
        
        // ✅ 添加 highlights 和 comparison 到 metadata
        responseMetadata = {
          ...responseMetadata,
          productsInfo: ourProductsInfo,
          highlights: finalIntentCard.highlights && finalIntentCard.highlights.length > 0 ? finalIntentCard.highlights : undefined,
          comparison: (finalIntentCard as any).comparison || undefined
        };
        
        console.log('📦 [DEBUG] responseMetadata with highlights/comparison:', {
          hasHighlights: !!(finalIntentCard.highlights && finalIntentCard.highlights.length > 0),
          highlights: finalIntentCard.highlights,
          hasComparison: !!(finalIntentCard as any).comparison,
          comparison: (finalIntentCard as any).comparison
        });
      } else {
        // ✅ 非产品意图也保存 highlights 和 comparison（如果有）
        if ((finalIntentCard.highlights && finalIntentCard.highlights.length > 0) || (finalIntentCard as any).comparison) {
          responseMetadata = {
            ...responseMetadata,
            highlights: finalIntentCard.highlights && finalIntentCard.highlights.length > 0 ? finalIntentCard.highlights : undefined,
            comparison: (finalIntentCard as any).comparison || undefined
          };
        }
      }
      
      const aiMessage: ChatMessageType = {
        id: `ai_${Date.now()}`,
        content: aiResponse,
        sender: "ai",
        timestamp: new Date().toLocaleTimeString('zh-CN', {
          hour: '2-digit',
          minute: '2-digit'
        }),
        type: messageType,
        agent: currentAgent,
        metadata: responseMetadata
      };
      
      setMessages(prev => [...prev, aiMessage]);

      if (activeConversationId) {
        await saveMessageLocal(aiMessage, activeConversationId);
      }
      
      // ========== Step 3: Post-process - 静默保存记忆到 Mem0 ==========
      console.log('🧠 [三明治] Step 3: 静默保存记忆到 Mem0...');
      addMemory(userId, userMessage, aiResponse);
    } catch (error) {
      console.error('❌ AI回复生成失败:');
      console.error('❌ 错误对象:', error);
      console.error('❌ 错误消息:', error instanceof Error ? error.message : String(error));
      console.error('❌ 错误堆栈:', error instanceof Error ? error.stack : '无堆栈信息');
      
      const errorDetail = error instanceof Error ? error.message : '未知错误';

      const errorMessage: ChatMessageType = {
        id: `ai_error_${Date.now()}`,
        content: `抱歉，${errorDetail}`,
        sender: "ai",
        timestamp: new Date().toLocaleTimeString('zh-CN', {
          hour: '2-digit',
          minute: '2-digit'
        }),
        type: "text",
        agent: currentAgent
      };
      
      setMessages(prev => [...prev, errorMessage]);
      if (activeConversationId) {
        await saveMessageLocal(errorMessage, activeConversationId);
      }
    } finally {
      setIsAiTyping(false);
    }
  }, [currentAgent, products, orders, fetchProducts, fetchOrders, activeConversationId, saveMessageLocal, user, chatModel, useStream]);

  // 处理发送消息
  const handleSendMessage = useCallback(async (content: string) => {
    // 兜底：如果没有活跃对话，自动创建一个（用局部变量避免闭包过期）
    let currentConvId = activeConversationId;
    if (!currentConvId) {
      const newConv = await createNewConversation('新对话');
      if (!newConv?.id) {
        toast.error('创建对话失败');
        return;
      }
      currentConvId = newConv.id;
      activeConvIdRef.current = newConv.id;
      _activeConvId = newConv.id; // ★ 模块级变量，彻底绕过闭包
    }
    _activeConvId = currentConvId; // 已有对话也同步

    const userMessage: ChatMessageType = {
      id: `user_${Date.now()}`,
      content,
      sender: "user",
      timestamp: new Date().toLocaleTimeString('zh-CN', {
        hour: '2-digit',
        minute: '2-digit'
      }),
      type: "text"
    };

    setMessages(prev => [...prev, userMessage]);

    await saveMessageLocal(userMessage, currentConvId);
    await simulateAIResponse(content);
  }, [simulateAIResponse, activeConversationId, saveMessageLocal, createNewConversation]);

  // 处理新建对话
  const handleNewConversation = useCallback(async (e?: React.MouseEvent) => {
    if (e) {
      e.preventDefault();
      e.stopPropagation();
    }
    
    try {
      setMessages([]);
      setIsAiTyping(true);
      
      const newConv = await createNewConversation('新对话');
      if (newConv) {
        setActiveConversationId(newConv.id);

        const welcomeMessage: ChatMessageType = {
          id: `welcome_${Date.now()}`,
          content: "",
          sender: "ai",
          timestamp: new Date().toLocaleTimeString('zh-CN', {
            hour: '2-digit',
            minute: '2-digit'
          }),
          type: "agent_intro",
          agent: AI_AGENTS.general,
          metadata: {
            agentIntroInfo: {
              agent: AI_AGENTS.general
            }
          }
        };
        
        setMessages([welcomeMessage]);
        
        // 为新用户推送欢迎优惠券
        setTimeout(async () => {
          const welcomeCoupons = await getWelcomeCoupons();
          if (welcomeCoupons.length > 0) {
            const firstCoupon = welcomeCoupons[0];
            const couponMessage: ChatMessageType = {
              id: `welcome_coupon_${Date.now()}`,
              content: "🎁 欢迎您！为您准备了新人专享优惠券：",
              sender: "ai",
              timestamp: new Date().toLocaleTimeString('zh-CN', {
                hour: '2-digit',
                minute: '2-digit'
              }),
              type: "coupon",
              agent: AI_AGENTS.general,
              metadata: {
                couponInfo: {
                  id: firstCoupon.id,
                  code: firstCoupon.code,
                  name: firstCoupon.name,
                  description: firstCoupon.description,
                  type: firstCoupon.type,
                  discount_value: firstCoupon.discount_value,
                  min_purchase_amount: firstCoupon.min_purchase_amount,
                  max_discount_amount: firstCoupon.max_discount_amount,
                  end_date: firstCoupon.end_date,
                  scope: firstCoupon.scope
                }
              }
            };
            
            setMessages(prev => [...prev, couponMessage]);
            if (newConv?.id) {
              await saveMessageLocal(couponMessage, newConv.id);
            }
          }
        }, 1000);
        
        toast.success('已创建新对话');
      }
    } catch (error) {
      console.error('创建新对话失败:', error);
      toast.error('创建新对话失败');
    } finally {
      setIsAiTyping(false);
    }
  }, [createNewConversation]);

  // 处理对话切换
  const handleConversationSelect = useCallback(async (conversationId: string, e?: React.MouseEvent) => {
    if (e) {
      e.preventDefault();
      e.stopPropagation();
    }
    
    if (conversationId === activeConversationId) return;
    
    setMessages([]);
    setActiveConversationId(conversationId);
    
    // 直接切换对话
    try {
      await selectConversation(conversationId);
    } catch (error) {
      console.error('切换对话失败:', error);
      toast.error('切换对话失败');
    }
  }, [activeConversationId, selectConversation]);

  // 处理产品详情查看
  const handleViewProductDetails = useCallback((productId: string) => {
    setSelectedProductId(productId);
    setShowProductDetail(true);
  }, []);

  // 处理添加到购物车
  const handleAddToCart = useCallback((product: any) => {
    addItem(product);
    toast.success(`${product.name} 已添加到购物车`);
  }, [addItem]);

  // 处理刷新对话
  const handleRefreshConversation = useCallback(async () => {
    if (!activeConversationId || !user) return;
    
    try {
      await selectConversation(activeConversationId);
      toast.success('对话内容已刷新');
    } catch (error) {
      console.error('刷新对话失败:', error);
      toast.error('刷新对话失败');
    }
  }, [activeConversationId, user, selectConversation]);

  // 处理重命名对话
  const handleRenameConversation = useCallback(async (conversationId: string, newTitle: string) => {
    try {
      await updateConversation(conversationId, { title: newTitle });
      toast.success('对话重命名成功');
    } catch (error) {
      console.error('重命名对话失败:', error);
      toast.error('重命名对话失败');
    }
  }, [updateConversation]);

  // 处理删除对话
  const handleDeleteConversation = useCallback(async (conversationId: string) => {
    try {
      await deleteConversation(conversationId);
    } catch (error) {
      console.error('删除对话失败:', error);
      toast.error('删除对话失败');
    }
  }, [deleteConversation]);

  // 组件加载时优先加载会话，其他数据懒加载
  useEffect(() => {
    console.log('ChatPage: useEffect 开始执行, user 存在:', !!user);
    
    if (!user) {
      console.log('ChatPage: 没有用户，设置 isLoading = false');
      setIsLoading(false);
      return;
    }

    const loadData = async () => {
      console.log('ChatPage: 开始加载数据, user:', user?.id);
      setIsLoading(true);
      
      try {
        // 优先加载会话列表
        console.log('ChatPage: 加载会话列表...');
        const conversationList = await loadConversations();
        console.log('ChatPage: 会话列表加载完成, 数量:', conversationList?.length);
        
        // Handle conversation selection logic here to avoid dependency loop
        if (conversationList && conversationList.length > 0 && !activeConversationId) {
          console.log('ChatPage: 设置活跃会话:', conversationList[0].id);
          setActiveConversationId(conversationList[0].id);
        } else if (!conversationList || conversationList.length === 0) {
          console.log('ChatPage: 没有会话，清空状态');
          setActiveConversationId(null);
        }
        
        console.log('ChatPage: 会话数据处理完成');
        
      } catch (error) {
        console.error('ChatPage: 加载数据失败:', error);
      }
      
      // 无论成功失败都设置加载完成
      console.log('ChatPage: 设置 isLoading = false');
      setIsLoading(false);
    };
    
    // 使用 setTimeout 避免阻塞
    setTimeout(() => {
      loadData();
    }, 0);
    
    // 延迟加载其他数据，不阻塞界面
    setTimeout(() => {
      console.log('ChatPage: 开始加载产品数据');
      fetchProducts().catch(console.error);
    }, 1000);
    
    setTimeout(() => {
      console.log('ChatPage: 开始加载订单数据');  
      fetchOrders().catch(console.error);
    }, 2000);

  }, [user]);

  // 当活动对话变化时，加载对应的消息
  useEffect(() => {
    if (activeConversationId && user) {
      loadMessages(activeConversationId);
    } else if (!activeConversationId) {
      setMessages([]);
    }
  }, [activeConversationId, user]);

  // Auto scroll to bottom when new messages arrive
  useEffect(() => {
    if (scrollAreaRef.current) {
      const scrollElement = scrollAreaRef.current.querySelector('[data-radix-scroll-area-viewport]');
      if (scrollElement) {
        scrollElement.scrollTop = scrollElement.scrollHeight;
      }
    }
  }, [messages, isAiTyping]);

  // 处理来自移动端的初始消息
  useEffect(() => {
    const initialMessage = location.state?.initialMessage;
    if (initialMessage && activeConversationId) {
      // 清空 location state 避免重复处理
      window.history.replaceState({}, document.title);
      // 发送初始消息
      setTimeout(() => {
        handleSendMessage(initialMessage);
      }, 500);
    }
  }, [activeConversationId, location.state, handleSendMessage]);

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-center">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mx-auto mb-4"></div>
          <p>正在加载聊天页面...</p>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-screen bg-background relative">
      {/* 移动端遮罩：点击关闭侧边栏 */}
      {sidebarVisible && (
        <div
          className="md:hidden fixed inset-0 bg-black/40 z-40 animate-in fade-in"
          onClick={() => setSidebarVisible(false)}
          aria-hidden="true"
        />
      )}

      {/* 侧边栏：桌面端占位，移动端浮层 */}
      <div
        className={`bg-sidebar border-r border-border h-screen flex-shrink-0 transition-all duration-300 ease-in-out
          fixed md:relative top-0 left-0 z-50
          ${sidebarVisible
            ? 'w-[85vw] max-w-xs md:w-80 translate-x-0'
            : 'w-0 -translate-x-full md:translate-x-0 overflow-hidden'}
        `}
      >
        {sidebarVisible && (
          <ChatSidebar
            conversations={conversations}
            activeConversationId={activeConversationId}
            onNewConversation={handleNewConversation}
            onConversationSelect={handleConversationSelect}
            onCloseSidebar={() => setSidebarVisible(false)}
            onRenameConversation={handleRenameConversation}
            onDeleteConversation={handleDeleteConversation}
          />
        )}
      </div>
      
      {/* 主内容区域 */}
      <div className="flex-1 flex flex-col h-screen">
        {/* Header + AI引擎开关 */}
        <div className="flex-shrink-0">
          <div className="flex items-center justify-between">
            <div className="flex-1">
              <Header 
                onToggleSidebar={() => setSidebarVisible(!sidebarVisible)}
                showSidebarToggle={true}
              />
            </div>
          </div>
        </div>
        
        {/* 聊天区域 */}
        <div className="flex-1 flex flex-col overflow-hidden">
          {/* 聊天消息区域 */}
          <div className="relative flex-1 overflow-hidden">
          <ScrollArea className="h-full px-4 pb-2" ref={scrollAreaRef}>
            <div className="space-y-4 max-w-4xl mx-auto py-4">
              {messages.length === 0 && !isAiTyping && !activeConversationId && conversations.length === 0 ? (
                <div className="flex flex-col items-center justify-center min-h-[400px] text-center gap-8 py-8">
                  <div className="text-muted-foreground">
                    <div className="text-6xl mb-4">💬</div>
                    <h3 className="text-lg font-medium mb-2">欢迎使用AI智能购物助手</h3>
                    <p className="text-sm">{user ? '点击"新建对话"开始您的第一次对话' : '直接在下方输入消息即可开始体验，登录后可保存历史记录'}</p>
                  </div>
                  
                </div>
              ) : messages.length === 0 && !isAiTyping && !activeConversationId ? (
                <div className="flex flex-col items-center justify-center h-full min-h-[400px] text-center">
                  <div className="text-muted-foreground">
                    <div className="text-6xl mb-4">📝</div>
                    <h3 className="text-lg font-medium mb-2">请选择一个对话</h3>
                    <p className="text-sm">从左侧对话列表中选择一个对话开始</p>
                  </div>
                </div>
              ) : (
                <>
                  {messages.map(message => 
                    <ChatMessage 
                      key={message.id} 
                      message={message} 
                      onCopy={() => {}} 
                      onFeedback={() => {}} 
                      onAddToCart={handleAddToCart} 
                      onViewDetails={handleViewProductDetails} 
                      onViewAfterSalesDetails={() => {}} 
                      onContactAfterSalesService={() => {}} 
                    />
                  )}
                  {isAiTyping && <TypingIndicator />}
                  {(() => {
                    // 找到最后一条 user 消息位置
                    const lastUserIdx = [...messages].map((m, i) => ({ m, i })).reverse().find(({ m }) => m.sender === 'user')?.i ?? -1;
                    if (lastUserIdx < 0) return null;
                    const lastUser = messages[lastUserIdx];
                    // 该 user 消息之后是否已有携带 picks 的 assistant 消息
                    const hasPicksAfter = messages.slice(lastUserIdx + 1).some(
                      (m: any) => m.sender === 'ai' && Array.isArray(m?.metadata?.productsInfo) && m.metadata.productsInfo.length > 0
                    );
                    if (!isAiTyping || hasPicksAfter) return null;
                    const text = lastUser.content ?? '';
                    const shoppingHint = /手机|相机|耳机|平板|电脑|笔记本|推荐|对比|比较|介绍|有哪些|哪款|哪个|性价比|预算|价格|多少钱|苹果|小米|华为|vivo|oppo|三星|redmi|iphone|拍照|游戏|续航|轻薄|旗舰/i;
                    if (!text || !shoppingHint.test(text)) return null;
                    return (
                      <div className="animate-fade-in transition-opacity duration-300">
                        <ProductCardSkeletonRow count={3} />
                      </div>
                    );
                  })()}
                  {/* 底部间距，确保最后一条消息不被输入框遮挡 */}
                  <div className="h-4"></div>
                </>
              )}
            </div>
          </ScrollArea>
          <ScrollToBottomButton scrollAreaRef={scrollAreaRef} />
          </div>

          {/* 输入区域 - 固定在底部 */}
          <div className="flex-shrink-0">
            <ChatInput onSendMessage={handleSendMessage} onImageUpload={() => {}} disabled={isAiTyping} />
          </div>
        </div>
      </div>

      {/* 弹窗组件 */}
      <ProductDetailDialog 
        open={showProductDetail} 
        onOpenChange={setShowProductDetail} 
        productId={selectedProductId}
        onBuyNow={() => setCheckoutOpen(true)}
      />

      <AfterSalesDetailDialog 
        open={showAfterSalesDetail} 
        onOpenChange={setShowAfterSalesDetail} 
        afterSalesId={selectedAfterSalesId} 
      />

      <AfterSalesRequestDialog 
        open={showAfterSalesRequest}
        onOpenChange={setShowAfterSalesRequest} 
        orderId={selectedOrderForAfterSales?.id || ""} 
        orderNumber={selectedOrderForAfterSales?.orderNumber || ""} 
        products={selectedOrderForAfterSales?.products || []} 
        onSuccess={() => {}} 
      />

      <CheckoutDialog 
        open={checkoutOpen} 
        onOpenChange={setCheckoutOpen} 
      />
    </div>
  );
}