import type { SseEventType } from './types';
import { buildAuthHeaders } from './hmac';

function randomUUID(): string {
  try { return crypto.randomUUID(); } catch { /* HTTP 环境不可用 */ }
  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);
  });
}

export interface ParsedSseEvent {
  type: SseEventType;
  data: Record<string, unknown>;
}

export interface ChatStreamOptions {
  deviceId: string;
  deviceType: string;
  text: string;
  conversationId?: string;
  clientMessageId?: string;
  onEvent: (event: ParsedSseEvent) => void;
  onError: (error: Error) => void;
  onComplete: () => void;
}

export function parseSseChunk(previous: string, chunk: string): { events: ParsedSseEvent[]; remainder: string } {
  const buffer = previous + chunk;
  const rawEvents = buffer.split('\n\n');
  const remainder = rawEvents.pop() ?? '';
  const events: ParsedSseEvent[] = [];

  for (const raw of rawEvents) {
    const eventMatch = raw.match(/^event:\s*(.+)$/m);
    const dataMatch = raw.match(/^data:\s*(.+)$/m);
    if (!eventMatch || !dataMatch) continue;

    const type = eventMatch[1].trim() as SseEventType;
    try {
      events.push({ type, data: JSON.parse(dataMatch[1]) });
    } catch {
      events.push({ type: 'error', data: { message: 'SSE 数据解析失败' } });
    }
  }

  return { events, remainder };
}

const API_BASE = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:6040/api/v1';

export function connectChatStream(options: ChatStreamOptions): AbortController {
  const controller = new AbortController();
  const body = JSON.stringify({
    deviceContext: {
      deviceId: options.deviceId,
      deviceType: options.deviceType,
    },
    message: {
      type: 'text',
      text: options.text,
      clientMessageId: options.clientMessageId ?? randomUUID(),
    },
    conversationId: options.conversationId || undefined,
  });

  const path = '/api/v1/agent/chat/stream';
  const url = `${API_BASE}/agent/chat/stream`;

  buildAuthHeaders('POST', path, body).then((headers) => {
    if (controller.signal.aborted) return;

    fetch(url, {
      method: 'POST',
      headers: { ...headers, 'Content-Type': 'application/json', Accept: 'text/event-stream' },
      body,
      signal: controller.signal,
    })
      .then(async (response) => {
        if (!response.ok) {
          const errText = await response.text().catch(() => '');
          options.onError(new Error(errText || `SSE 连接失败: HTTP ${response.status}`));
          return;
        }
        const reader = response.body?.getReader();
        if (!reader) {
          options.onError(new Error('浏览器不支持 ReadableStream'));
          return;
        }
        const decoder = new TextDecoder();
        let remainder = '';

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

          const chunk = decoder.decode(value, { stream: true });
          const result = parseSseChunk(remainder, chunk);
          remainder = result.remainder;

          for (const event of result.events) {
            if (event.type === 'completed') {
              options.onComplete();
              return;
            }
            options.onEvent(event);
          }
        }
        options.onComplete();
      })
      .catch((err) => {
        if (err.name !== 'AbortError') {
          options.onError(err);
        }
      });
  });

  return controller;
}
