import path from "node:path";

import type { AgentMeta, AgentParseResult, AgentSpec } from "./types.js";

type PiAssistantMessage = {
  role?: string;
  content?: Array<{ type?: string; text?: string }>;
  usage?: { input?: number; output?: number };
  model?: string;
  provider?: string;
  stopReason?: string;
};

function parsePiJson(raw: string): AgentParseResult {
  const lines = raw.split(/\n+/).filter((l) => l.trim().startsWith("{"));
  let lastMessage: PiAssistantMessage | undefined;
  for (const line of lines) {
    try {
      const ev = JSON.parse(line) as {
        type?: string;
        message?: PiAssistantMessage;
      };
      // Pi emits a stream; we only care about the terminal assistant message_end.
      if (ev.type === "message_end" && ev.message?.role === "assistant") {
        lastMessage = ev.message;
      }
    } catch {
      // ignore
    }
  }
  const text =
    lastMessage?.content
      ?.filter((c) => c?.type === "text" && typeof c.text === "string")
      .map((c) => c.text)
      .join("\n")
      ?.trim() ?? undefined;
  const meta: AgentMeta | undefined = lastMessage
    ? {
        model: lastMessage.model,
        provider: lastMessage.provider,
        stopReason: lastMessage.stopReason,
        usage: lastMessage.usage,
      }
    : undefined;
  return { text, meta };
}

export const piSpec: AgentSpec = {
  kind: "pi",
  isInvocation: (argv) => argv.length > 0 && path.basename(argv[0]) === "pi",
  buildArgs: (ctx) => {
    const argv = [...ctx.argv];
    // Non-interactive print + JSON
    if (!argv.includes("-p") && !argv.includes("--print")) {
      argv.splice(argv.length - 1, 0, "-p");
    }
    if (
      ctx.format === "json" &&
      !argv.includes("--mode") &&
      !argv.some((a) => a === "--mode")
    ) {
      argv.splice(argv.length - 1, 0, "--mode", "json");
    }
    // Session defaults
    // Identity prefix optional; Pi usually doesn't need it, but allow injection
    if (!(ctx.sendSystemOnce && ctx.systemSent) && argv[ctx.bodyIndex]) {
      const existingBody = argv[ctx.bodyIndex];
      argv[ctx.bodyIndex] = [ctx.identityPrefix, existingBody]
        .filter(Boolean)
        .join("\n\n");
    }
    return argv;
  },
  parseOutput: parsePiJson,
};
