/**
 * Consumer Chat Edge Function Client
 * C端消费者聊天 —— 直接大模型调用（AI Hub）
 */

import { supabase } from '@/integrations/supabase/client';
import { generateUUID } from '@/utils/idGenerator';

const SUPABASE_URL = import.meta.env.VITE_SUPABASE_URL;
const SUPABASE_ANON_KEY = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY;

interface CozeRequestOptions {
  message: string;
  userId: string;
  conversationId?: string;
  userContext?: string;  // Mem0 记忆上下文
  product?: {
    id: string;
    title: string;
    description?: string;
    price?: number;
  };
  catalog?: Array<{
    id: string;
    name: string;
    price: number;
    stock_quantity?: number;
    category?: string;
    description?: string;
  }>;
}

interface CozeResponse {
  title: string;
  intent: "SHOPPING" | "AFTERSALES" | "GENERAL" | "COMPARE" | "SEARCH" | string;
  sentiment: "POSITIVE" | "NEUTRAL" | "NEGATIVE";
  highlights: string[];
  picks: Array<{
    product_id: string;
    note: string;
    source?: string;
  }>;
  comparison?: string;
  next: string[];
  meta: {
    platform: string;
    user: string;
    catalog_count: number;
    probe_id: string;
  };
  error?: string;
  trace_id?: string;
  conversation_id?: string;
  answer?: string;
}

type StreamDonePayload = Partial<CozeResponse> & {
  type?: 'done';
};

function processStreamLine(
  line: string,
  state: { fullContent: string; doneData: StreamDonePayload | null },
  onText?: (text: string) => void
) {
  const trimmedLine = line.trim();
  if (!trimmedLine || trimmedLine.startsWith(':') || trimmedLine === 'data: [DONE]') return;
  if (!trimmedLine.startsWith('data:')) return;

  const jsonStr = trimmedLine.slice(5).trim();
  try {
    const event = JSON.parse(jsonStr);
    if (event.type === 'text') {
      const content = event.content || '';
      state.fullContent += content;
      onText?.(content);
    } else if (event.type === 'done') {
      state.doneData = event;
    } else if (event.type === 'error') {
      throw new Error(event.message || 'AI 流式响应失败');
    }
  } catch (error) {
    // JSON.parse 抛出 SyntaxError，应静默跳过该行
    // 只有业务层主动抛出的 Error 才向上传播（如 type==='error' 事件）
    if (error instanceof SyntaxError) {
      if (jsonStr && !jsonStr.startsWith('{')) {
        state.fullContent += jsonStr;
      }
      return;
    }
    throw error;
  }
}

export async function callCozeEdge(
  options: CozeRequestOptions & { onText?: (text: string) => void }
): Promise<{
  data: CozeResponse | null;
  traceId: string;
  status: number;
  error?: string;
}> {
  const traceId = generateUUID();

  const requestBody = {
    message: options.message,
    conversationId: options.conversationId || '',
    inputs: {
      user_id: options.userId || 'guest',
      trace_id: traceId,
      user_context: options.userContext || '',
      product: options.product,
      catalog: options.catalog || []
    }
  };

  try {
    console.log('🚀 [CHAT CLIENT] 调用 ai-chat-stream');
    console.log('📤 消息:', options.message?.substring(0, 60));

    const { data: { session } } = await supabase.auth.getSession();

    console.log('🔍 [CHAT CLIENT] Fetching:', `${SUPABASE_URL}/functions/v1/dify-chat-stream`);
    console.log('🔍 [CHAT CLIENT] Auth mode:', session?.access_token ? 'session token' : 'anon key');

    // 单次调用 + 超时保护（65秒）
    const invokePromise = fetch(`${SUPABASE_URL}/functions/v1/dify-chat-stream`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${session?.access_token || SUPABASE_ANON_KEY}`,
        'X-Trace-Id': traceId,
        'X-User-Id': options.userId || 'guest'
      },
      body: JSON.stringify(requestBody)
    });

    const timeoutPromise = new Promise<never>((_, reject) => {
      setTimeout(() => reject(new Error('AI响应超时，请重新发送消息')), 65000);
    });

    const response = await Promise.race([invokePromise, timeoutPromise]);

    if (!response.ok) {
      const errorText = await response.text();
      console.error('❌ [CHAT CLIENT] 请求失败:', response.status, errorText);
      throw new Error(`请求失败 (${response.status}): ${errorText.substring(0, 200)}`);
    }

    if (!response.body) {
      throw new Error('响应体为空');
    }

    // ─── 读取 SSE 流 ───
    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    const onText = options.onText;
    const state = { fullContent: '', doneData: null as StreamDonePayload | null };
    let buffer = '';

    // rAF 批量包装 onText：每帧最多触发一次，确保浏览器在帧之间有机会绘制
    // 根因：await setTimeout(0) 从 Promise 延续中创建不触发 4ms 嵌套惩罚，
    // 全部回调在 <1ms 内触发完毕，浏览器只在 VSync 边界绘制一次 → 用户看不到流式效果
    let pendingText = '';
    let rafId: number | null = null;

    const batchedOnText = onText ? (text: string) => {
      pendingText += text;
      if (rafId === null) {
        rafId = requestAnimationFrame(() => {
          if (pendingText) {
            onText(pendingText);
            pendingText = '';
          }
          rafId = null;
        });
      }
    } : undefined;

    try {
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          if (buffer.trim()) processStreamLine(buffer, state, batchedOnText);
          break;
        }

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        buffer = lines.pop() || '';
        for (const line of lines) {
          processStreamLine(line, state, batchedOnText);
        }
      }
    } finally {
      // 确保 rAF 回调被取消、剩余文本被刷新，即使 processStreamLine 抛出异常也不会泄漏
      if (rafId !== null) {
        cancelAnimationFrame(rafId);
        rafId = null;
      }
      if (pendingText && onText) {
        onText(pendingText);
        pendingText = '';
      }
    }

    const rawData = { ...(state.doneData || {}), answer: state.fullContent };

    if (rawData.error) {
      return {
        data: null,
        traceId: rawData.meta?.probe_id || traceId,
        status: 200,
        error: `系统繁忙，请稍后再试（追踪码：${rawData.meta?.probe_id || traceId}）`
      };
    }

    if (!state.doneData && !state.fullContent) {
      return {
        data: null,
        traceId,
        status: 0,
        error: '响应数据为空'
      };
    }

    console.log('✅ [CHAT CLIENT] 成功获取响应, picks:', rawData.picks?.length || 0);

    const cozeResponse: CozeResponse = {
      title: rawData.title || options.message,
      intent: rawData.intent || "GENERAL",
      sentiment: rawData.sentiment || "NEUTRAL",
      highlights: rawData.highlights || [],
      picks: rawData.picks || [],
      comparison: rawData.comparison,
      next: rawData.next || [],
      meta: {
        platform: rawData.meta?.platform || 'ai-hub',
        user: rawData.meta?.user || options.userId,
        catalog_count: rawData.meta?.catalog_count ?? 0,
        probe_id: rawData.meta?.probe_id || traceId
      },
      conversation_id: rawData.conversation_id,
      answer: rawData.answer
    };

    return {
      data: cozeResponse,
      traceId: cozeResponse.meta.probe_id,
      status: 200
    };

  } catch (error) {
    console.error('❌ [CHAT CLIENT] 调用失败:', error);

    const errorMessage = error instanceof Error ? error.message : String(error);
    let friendlyMessage = '抱歉，系统暂时繁忙';

    if (errorMessage.includes('Failed to fetch') || errorMessage.includes('NetworkError')) {
      friendlyMessage = '网络连接不稳定，请重新发送消息试试';
    } else if (errorMessage.includes('timeout') || errorMessage.includes('超时')) {
      friendlyMessage = 'AI响应超时，请重新发送消息';
    } else if (errorMessage.includes('AI_HUB') || errorMessage.includes('LOVABLE')) {
      friendlyMessage = 'AI服务未配置，请联系管理员';
    }

    return {
      data: null,
      traceId,
      status: 0,
      error: friendlyMessage
    };
  }
}
