/**
 * dify-chat-stream Edge Function
 * C端消费者聊天 - Dify 流式输出版本
 * 
 * 优先使用 Dify，失败时回退到 Coze
 */

import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.57.4';

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-trace-id, x-user-id',
  'Access-Control-Allow-Methods': 'POST, OPTIONS',
};

interface ChatRequest {
  message: string;
  conversationId?: string;
  inputs: {
    user_id?: string;
    trace_id: string;
    user_context?: string;
    catalog?: Array<{
      id: string;
      name: string;
      price: number;
      stock_quantity?: number;
      category?: string;
      description?: string;
    }>;
  };
}

// 尝试从文本中提取完整的结构化 JSON（包含 picks/intent/highlights/comparison/next 等字段）
function parseStructuredPayload(text: string): any | null {
  const candidates: string[] = [];
  const fencedMatch = text.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
  if (fencedMatch) candidates.push(fencedMatch[1]);
  const trimmed = text.trim();
  if (trimmed.startsWith('{')) candidates.push(trimmed);
  // 扫描第一个 { 到最后一个 } 之间的内容
  const firstBrace = text.indexOf('{');
  const lastBrace = text.lastIndexOf('}');
  if (firstBrace >= 0 && lastBrace > firstBrace) {
    candidates.push(text.slice(firstBrace, lastBrace + 1));
  }
  for (const candidate of candidates) {
    try {
      const parsed = JSON.parse(candidate);
      if (parsed && typeof parsed === 'object' && (parsed.picks || parsed.intent || parsed.highlights)) {
        return parsed;
      }
    } catch {
      // 继续
    }
  }
  return null;
}

// 解析文本中的 picks - 支持三种格式：① 纯 JSON 对象 ② ```json``` 代码块 ③ 文本中的 JSON 片段
function parsePicksFromText(text: string, catalog: any[]): Array<{ product_id: string; note: string }> {
  const picks: Array<{ product_id: string; note: string }> = [];
  const candidates: string[] = [];

  // 候选 1：```json ... ``` 代码块
  const fencedMatch = text.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
  if (fencedMatch) candidates.push(fencedMatch[1]);

  // 候选 2：整个文本 trim 后若以 { 开头，尝试整体解析
  const trimmed = text.trim();
  if (trimmed.startsWith('{')) candidates.push(trimmed);

  // 候选 3：搜索 "picks" 关键字附近的 JSON 数组片段
  const picksArrMatch = text.match(/"picks"\s*:\s*(\[[\s\S]*?\])/);
  if (picksArrMatch) candidates.push(`{"picks":${picksArrMatch[1]}}`);

  for (const candidate of candidates) {
    try {
      const parsed = JSON.parse(candidate);
      if (parsed?.picks && Array.isArray(parsed.picks)) {
        for (const p of parsed.picks) {
          if (!p?.product_id) continue;
          const exists = catalog.some(c => c.id === p.product_id);
          if (exists && !picks.some(pick => pick.product_id === p.product_id)) {
            picks.push({ product_id: p.product_id, note: p.note || '' });
          }
        }
        if (picks.length > 0) return picks;
      }
    } catch {
      // 继续尝试下一个候选
    }
  }

  // 兜底候选 4：扫描文本中所有 UUID，匹配 catalog
  if (picks.length === 0) {
    const uuidRegex = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
    const found = text.match(uuidRegex) || [];
    for (const id of found) {
      const product = catalog.find(c => c.id === id);
      if (product && !picks.some(pick => pick.product_id === id)) {
        picks.push({ product_id: id, note: '' });
      }
    }
  }

  return picks;
}

// 检测意图
function detectIntent(message: string, answer: string): string {
  const shoppingKeywords = ['买', '购', '推荐', '价格', '多少钱', '手机', '电脑'];
  const afterSalesKeywords = ['退货', '换货', '售后', '维修'];
  const compareKeywords = ['对比', '比较', '哪个更好'];
  if (compareKeywords.some(kw => message.includes(kw))) return 'COMPARE';
  if (shoppingKeywords.some(kw => message.includes(kw)) || answer.includes('picks')) return 'SHOPPING';
  if (afterSalesKeywords.some(kw => message.includes(kw))) return 'AFTERSALES';
  return 'GENERAL';
}

// 构建产品目录 prompt
function buildCatalogPrompt(catalog: any[]): string {
  if (catalog.length === 0) return '';
  return `\n\n## 可用产品目录（共${catalog.length}个，请从这里选择推荐）：\n${
    catalog.slice(0, 30).map(p => `• ID="${p.id}" | ${p.name} | ¥${p.price} | 库存:${p.stock_quantity ?? '未知'}`).join('\n')
  }\n\n当推荐产品时，必须在回复末尾包含：\n\`\`\`json\n{"picks": [{"product_id": "从上面目录复制的真实ID", "note": "推荐理由"}]}\n\`\`\`\n严格规则：product_id 必须从产品目录中复制，禁止编造！`;
}

Deno.serve(async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }

  const traceId = req.headers.get('x-trace-id') || crypto.randomUUID();

  try {
    const body: ChatRequest = await req.json();
    const { message, conversationId, inputs } = body;

    console.log('📥 [dify-chat-stream] request:', {
      trace_id: traceId,
      message: message?.substring(0, 50),
      catalogCount: inputs?.catalog?.length || 0,
      conversationId: conversationId || '(new)',
    });

    const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
    const supabaseKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
    const supabase = createClient(supabaseUrl, supabaseKey);

    // 获取权威产品目录并与前端传入目录合并，避免前端截断导致真实 ID 被误过滤
    const inputCatalog = Array.isArray(inputs.catalog) ? inputs.catalog : [];
    const { data: products } = await supabase
      .from('products')
      .select('id, name, price, stock_quantity, category, description, brand, is_hot, is_recommended')
      .eq('is_active', true)
      .order('is_hot', { ascending: false })
      .order('is_recommended', { ascending: false })
      .limit(500);
    const catalogById = new Map<string, any>();
    [...inputCatalog, ...(products || [])].forEach((product: any) => {
      if (product?.id) catalogById.set(product.id, product);
    });
    const catalog = Array.from(catalogById.values());

    const DIFY_API_KEY = Deno.env.get('DIFY_API_KEY');
    const DIFY_BASE_URL = Deno.env.get('DIFY_BASE_URL') || 'https://api.dify.ai/v1';

    if (!DIFY_API_KEY) {
      throw new Error('DIFY_API_KEY not configured');
    }

    // 构建 Dify 请求 - 只发送用户原始消息，不注入目录（让 Dify Agent 自行处理）
    const difyBody: any = {
      inputs: {
        user_context: inputs.user_context || '',
      },
      query: message,
      response_mode: 'streaming',
      user: inputs.user_id || 'anonymous',
    };

    // 如果有对话ID，传入以维持多轮对话
    if (conversationId) {
      difyBody.conversation_id = conversationId;
    }

    console.log('🚀 [dify-chat-stream] Calling Dify API...');

    const difyResponse = await fetch(`${DIFY_BASE_URL}/chat-messages`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${DIFY_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(difyBody),
    });

    if (!difyResponse.ok) {
      const errorText = await difyResponse.text();
      console.error('❌ [dify-chat-stream] Dify API error:', difyResponse.status, errorText);
      throw new Error(`Dify API error: ${difyResponse.status} - ${errorText}`);
    }

    // 创建 SSE 流
    const encoder = new TextEncoder();
    let fullAnswer = '';
    let difyConversationId = conversationId || '';

    const stream = new ReadableStream({
      async start(controller) {
        try {
          const reader = difyResponse.body?.getReader();
          if (!reader) throw new Error('No response body');

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

          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) {
              if (!line.trim() || line.startsWith(':')) continue;

              let dataContent = line;
              if (line.startsWith('data:')) {
                dataContent = line.slice(5).trim();
              }
              if (!dataContent || dataContent === '[DONE]') continue;

              try {
                const parsed = JSON.parse(dataContent);
                const event = parsed.event;

                // Dify SSE 事件类型
                if (event === 'message' || event === 'agent_message') {
                  const content = parsed.answer || '';
                  if (content) {
                    fullAnswer += content;
                    const sseData = JSON.stringify({ type: 'text', content });
                    controller.enqueue(encoder.encode(`data: ${sseData}\n\n`));
                  }
                  // 捕获 conversation_id
                  if (parsed.conversation_id) {
                    difyConversationId = parsed.conversation_id;
                  }
                } else if (event === 'message_end') {
                  if (parsed.conversation_id) {
                    difyConversationId = parsed.conversation_id;
                  }
                  console.log('✅ [dify-chat-stream] Dify message_end, conversation_id:', difyConversationId);
                } else if (event === 'error') {
                  console.error('❌ [dify-chat-stream] Dify error event:', parsed);
                  throw new Error(parsed.message || 'Dify streaming error');
                }
              } catch (e) {
                if (e instanceof SyntaxError) {
                  // 非 JSON，忽略
                } else {
                  throw e;
                }
              }
            }
          }

          // 如果 Dify 没有返回内容，发送友好错误
          if (!fullAnswer) {
            fullAnswer = '抱歉，AI助手暂时无法回复，请稍后再试。';
            const sseData = JSON.stringify({ type: 'text', content: fullAnswer });
            controller.enqueue(encoder.encode(`data: ${sseData}\n\n`));
          }

          // 打印 Dify 完整回复，便于调试是否包含商品ID
          console.log('📝 [dify-chat-stream] Full answer from Dify:\n' + fullAnswer);

          // 优先尝试解析 Dify 直接返回的结构化 JSON（包含 picks/intent/highlights/comparison/next）
          const structured = parseStructuredPayload(fullAnswer);

          let picks: Array<{ product_id: string; note: string }> = [];
          let intent = 'GENERAL';
          let highlights: string[] = [];
          let comparison: string | undefined;
          let next: string[] | undefined;
          let title: string | undefined;

          if (structured) {
            console.log('✅ [dify-chat-stream] Using structured payload from Dify');
            // 校验 picks 中的 product_id 必须存在于 catalog（防幻觉）
            const rawPicks = Array.isArray(structured.picks) ? structured.picks : [];
            const catalogIdSet = new Set(catalog.map((c: any) => c?.id).filter(Boolean));
            const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

            type PickAudit = { product_id: string | null; note: string | null; accepted: boolean; reasons: string[] };
            const pickAudit: PickAudit[] = rawPicks.map((p: any) => {
              const id = typeof p?.product_id === 'string' ? p.product_id.trim() : '';
              const reasons: string[] = [];
              if (!id) reasons.push('missing_product_id');
              else if (!uuidRegex.test(id)) reasons.push('invalid_uuid_format');
              else if (!catalogIdSet.has(id)) reasons.push('not_in_catalog');
              return { product_id: id || null, note: p?.note ?? null, accepted: reasons.length === 0, reasons };
            });

            const accepted = pickAudit.filter(a => a.accepted);
            const rejected = pickAudit.filter(a => !a.accepted);
            console.log(`📊 [dify-chat-stream] Pick audit — total:${pickAudit.length} accepted:${accepted.length} rejected:${rejected.length} catalog_size:${catalogIdSet.size}`);
            if (rejected.length > 0) {
              console.log('🚫 [dify-chat-stream] Rejected picks:', JSON.stringify(rejected, null, 2));
              // 对每个被拒的 ID，再做一次精确比对说明（区分「不在 catalog」vs「字段问题」）
              rejected.forEach(r => {
                if (r.product_id && r.reasons.includes('not_in_catalog')) {
                  const prefix = r.product_id.slice(0, 8);
                  const prefixHits = catalog
                    .filter((c: any) => typeof c?.id === 'string' && c.id.startsWith(prefix))
                    .map((c: any) => ({ id: c.id, name: c.name }));
                  console.log(`   ↳ ${r.product_id} not in catalog. Same-prefix(${prefix}) entries in catalog:`, JSON.stringify(prefixHits));
                }
              });
            }
            if (accepted.length > 0) {
              console.log('✅ [dify-chat-stream] Accepted picks:', JSON.stringify(
                accepted.map(a => {
                  const product = catalog.find((c: any) => c.id === a.product_id);
                  return { id: a.product_id, name: product?.name };
                })
              ));
            }

            picks = accepted.map(a => ({ product_id: a.product_id as string, note: a.note || '' }));
            intent = structured.intent || detectIntent(message, fullAnswer);
            highlights = Array.isArray(structured.highlights) ? structured.highlights : [];
            comparison = typeof structured.comparison === 'string' ? structured.comparison : undefined;
            next = Array.isArray(structured.next) ? structured.next : undefined;
            title = typeof structured.title === 'string' ? structured.title : undefined;
          } else {
            console.log('⚠️ [dify-chat-stream] No structured payload, falling back to text parsing');
            picks = parsePicksFromText(fullAnswer, catalog);
            intent = detectIntent(message, fullAnswer);
            highlights = fullAnswer.split(/[。！？\n]/).filter((s: string) => s.length > 10 && s.length < 100).slice(0, 3);
          }

          console.log('🔍 [dify-chat-stream] Parsed picks:', JSON.stringify(picks));
          const mentionedIds = catalog
            .filter(c => fullAnswer.includes(c.id))
            .map(c => ({ id: c.id, name: c.name }));
          console.log('🔎 [dify-chat-stream] Product IDs mentioned in text:', JSON.stringify(mentionedIds));

          // 发送最终元数据
          const finalData = JSON.stringify({
            type: 'done',
            intent,
            picks,
            highlights,
            ...(comparison ? { comparison } : {}),
            ...(next ? { next } : {}),
            ...(title ? { title } : {}),
            meta: {
              platform: 'dify-stream',
              user: inputs.user_id || 'anonymous',
              catalog_count: catalog.length,
              probe_id: traceId,
              source: structured ? 'dify-structured' : 'text-fallback',
            },
            conversation_id: difyConversationId,
          });

          controller.enqueue(encoder.encode(`data: ${finalData}\n\n`));
          controller.enqueue(encoder.encode('data: [DONE]\n\n'));
          controller.close();

          console.log('✅ [dify-chat-stream] Stream completed:', {
            answerLength: fullAnswer.length,
            picksCount: picks.length,
            intent,
            hasComparison: !!comparison,
            conversation_id: difyConversationId,
          });
        } catch (error) {
          console.error('❌ [dify-chat-stream] Stream error:', error);
          const errorData = JSON.stringify({
            type: 'error',
            message: (error instanceof Error ? error.message : '流式响应失败'),
          });
          controller.enqueue(encoder.encode(`data: ${errorData}\n\n`));
          controller.close();
        }
      },
    });

    return new Response(stream, {
      headers: {
        ...corsHeaders,
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
        'X-Trace-Id': traceId,
      },
    });
  } catch (error) {
    console.error('❌ [dify-chat-stream] Fatal error:', error);
    return new Response(
      JSON.stringify({ error: (error instanceof Error ? error.message : 'Unknown error')}),
      {
        status: 500,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      }
    );
  }
});
