// Zo API client for the Chat tab.
// Uses ZO_CLIENT_IDENTITY_TOKEN from the environment — no extra auth needed
// for the local Zo Computer sandbox.

const ENDPOINT = "https://api.zo.computer/zo/ask";

export interface ChatMessage {
  role: "user" | "assistant" | "system";
  content: string;
  ts: number;
}

export async function askZo(
  messages: ChatMessage[],
  onDelta: (text: string) => void,
  signal: AbortSignal,
): Promise<string> {
  const token = process.env.ZO_CLIENT_IDENTITY_TOKEN;
  if (!token) throw new Error("ZO_CLIENT_IDENTITY_TOKEN is not set");

  // Build a single prompt from the conversation. We don't pass history
  // server-side to keep this client simple — the assistant sees the full
  // transcript each turn.
  const lastUser = [...messages].reverse().find((m) => m.role === "user");
  if (!lastUser) return "";
  const transcript = messages
    .slice(-10)
    .map((m) => `${m.role === "user" ? "User" : "Zo"}: ${m.content}`)
    .join("\n\n");
  const prompt = transcript.endsWith(lastUser.content)
    ? transcript
    : transcript + `\n\nUser: ${lastUser.content}`;

  const resp = await fetch(ENDPOINT, {
    method: "POST",
    signal,
    headers: {
      authorization: token,
      "content-type": "application/json",
      accept: "text/event-stream",
    },
    body: JSON.stringify({
      input: prompt,
      model_name: "byok:048b600a-bf4b-4a7a-88f2-57621c471ed1",
      stream: true,
    }),
  });

  if (!resp.ok || !resp.body) {
    const txt = await resp.text().catch(() => "");
    throw new Error(`Zo API ${resp.status}: ${txt.slice(0, 200)}`);
  }

  const reader = resp.body.getReader();
  const decoder = new TextDecoder();
  let buf = "";
  let full = "";

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    buf += decoder.decode(value, { stream: true });
    const events = buf.split("\n\n");
    buf = events.pop() ?? "";
    for (const evt of events) {
      const line = evt.split("\n").find((l) => l.startsWith("data:"));
      if (!line) continue;
      const data = line.slice(5).trim();
      if (!data || data === "[DONE]") continue;
      try {
        const parsed = JSON.parse(data);
        const delta = parsed?.delta ?? parsed?.output ?? "";
        if (typeof delta === "string" && delta) {
          full += delta;
          onDelta(full);
        }
      } catch {
        // not JSON; treat as raw text delta
        if (data) {
          full += data;
          onDelta(full);
        }
      }
    }
  }
  return full;
}
