import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import { Type } from "typebox";

function textFromHtml(html: string): { title: string; content: string } {
  const title = html.match(/<title[^>]*>([^<]+)<\/title>/i)?.[1]?.trim() || "No title";
  const content = html
    .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, " ")
    .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, " ")
    .replace(/<[^>]+>/g, " ")
    .replace(/&nbsp;/g, " ")
    .replace(/&amp;/g, "&")
    .replace(/&lt;/g, "<")
    .replace(/&gt;/g, ">")
    .replace(/&quot;/g, '"')
    .replace(/\s+/g, " ")
    .trim();
  return { title, content };
}

async function fetchText(url: string, signal?: AbortSignal) {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 30000);
  const activeSignal = signal ?? controller.signal;
  try {
    const response = await fetch(url, {
      signal: activeSignal,
      headers: {
        "User-Agent": "Mozilla/5.0 Orquestra/1.0",
      },
    });
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return textFromHtml(await response.text());
  } finally {
    clearTimeout(timeout);
  }
}

export default function orquestraWebFetch(pi: ExtensionAPI) {
  pi.registerTool({
    name: "orquestra_web_fetch",
    label: "Orquestra Web Fetch",
    description: "Fetch a web page and return extracted text using a simple non-browser fetch.",
    parameters: Type.Object({
      url: Type.String({ description: "URL to fetch" }),
      limit: Type.Optional(Type.Integer({ minimum: 500, maximum: 20000, description: "Max characters to return" })),
    }),
    async execute(_toolCallId, params, signal) {
      const { title, content } = await fetchText(params.url, signal);
      const limit = params.limit ?? 8000;
      return {
        content: [{ type: "text", text: `Title: ${title}\n\nContent:\n${content.slice(0, limit)}` }],
        details: { title, url: params.url, characters: content.length },
      };
    },
  });
}
