/**
 * Telegram Stream Extension
 *
 * Sends live updates to Telegram as Pi runs tool calls.
 * Edits a single message in-place so it feels like streaming.
 *
 * Reads TELEGRAM_BOT_TOKEN, TELEGRAM_ALLOWED_USERS, TELEGRAM_STREAM_MSG_ID
 * from env — the bot sets TELEGRAM_STREAM_MSG_ID before spawning Pi.
 *
 * Usage: pi -e extensions/telegram-stream.ts
 */

import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { isToolCallEventType } from "@mariozechner/pi-coding-agent";

const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN ?? "";
const CHAT_ID = process.env.TELEGRAM_ALLOWED_USERS ?? "";
const MSG_ID = process.env.TELEGRAM_STREAM_MSG_ID ?? "";

const MAX_LEN = 3800; // Telegram max is 4096, leave room

function truncate(s: string): string {
  return s.length > MAX_LEN ? s.slice(0, MAX_LEN) + "\n…" : s;
}

async function editMessage(text: string) {
  if (!BOT_TOKEN || !CHAT_ID || !MSG_ID) return;
  try {
    await fetch(`https://api.telegram.org/bot${BOT_TOKEN}/editMessageText`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        chat_id: CHAT_ID,
        message_id: parseInt(MSG_ID),
        text: truncate(text),
        parse_mode: "Markdown",
      }),
    });
  } catch (_) {}
}

export default function (pi: ExtensionAPI) {
  const steps: string[] = [];
  const startTimes: Map<string, number> = new Map();

  function render(currentStep?: string): string {
    const lines = ["⚙️ *Pi is working...*\n"];
    for (const s of steps) lines.push(s);
    if (currentStep) lines.push(currentStep);
    return lines.join("\n");
  }

  pi.on("tool_call", async (event, _ctx) => {
    let label = "";

    if (isToolCallEventType("bash", event)) {
      const cmd = event.input.command ?? "";
      const short = cmd.length > 80 ? cmd.slice(0, 80) + "…" : cmd;
      label = `🔄 \`${short}\``;
    } else {
      label = `🔄 \`${event.toolName}\``;
    }

    startTimes.set(event.toolName + event.toolCallId, Date.now());
    await editMessage(render(label));
  });

  pi.on("tool_execution_end", async (event) => {
    const key = event.toolName + (event as any).toolCallId;
    const elapsed = startTimes.has(key) ? ((Date.now() - startTimes.get(key)!) / 1000).toFixed(1) : "?";
    startTimes.delete(key);

    let label = "";
    if (event.toolName === "bash") {
      const result = (event.result ?? "").toString().trim();
      const preview = result.split("\n").slice(0, 3).join("\n");
      const short = preview.length > 120 ? preview.slice(0, 120) + "…" : preview;
      label = `✅ \`bash\` _(${elapsed}s)_${short ? "\n```\n" + short + "\n```" : ""}`;
    } else {
      label = `✅ \`${event.toolName}\` _(${elapsed}s)_`;
    }

    steps.push(label);
    // Keep last 10 steps to avoid message getting too long
    if (steps.length > 10) steps.shift();

    await editMessage(render());
  });

  pi.on("agent_end", async (_event) => {
    const summary = steps.length > 0
      ? `✅ *Done!* _(${steps.length} steps)_`
      : `✅ *Done!*`;
    await editMessage(render() + "\n\n" + summary);
  });
}
