import type { AgentTool } from "@jaeswift/jae-agent-core";
import type { ToolResultMessage } from "@jaeswift/jae-ai";
import { Type } from "@sinclair/typebox";
import { html } from "lit";
import { Globe } from "lucide";
import { registerToolRenderer, renderHeader } from "./renderer-registry.js";
import type { ToolRenderer, ToolRenderResult } from "./types.js";

const TOOL_SERVER =
	typeof window !== "undefined"
		? (window as any).__JAE_TOOL_SERVER__ || "http://localhost:7700"
		: "http://localhost:7700";

const browserSchema = Type.Object({
	action: Type.Union(
		[
			Type.Literal("navigate"),
			Type.Literal("click"),
			Type.Literal("type"),
			Type.Literal("scroll"),
			Type.Literal("back"),
			Type.Literal("screenshot"),
			Type.Literal("text"),
			Type.Literal("eval"),
		],
		{ description: "Browser action to perform" },
	),
	url: Type.Optional(Type.String({ description: "URL to navigate to" })),
	x: Type.Optional(Type.Number({ description: "Click X coordinate" })),
	y: Type.Optional(Type.Number({ description: "Click Y coordinate" })),
	text: Type.Optional(Type.String({ description: "Text to type" })),
	selector: Type.Optional(Type.String({ description: "CSS selector to type into" })),
	dy: Type.Optional(Type.Number({ description: "Scroll delta Y pixels" })),
	script: Type.Optional(Type.String({ description: "JavaScript to evaluate in page" })),
});

export interface BrowserDetails {
	action: string;
	url?: string;
	title?: string;
	screenshot?: string;
	text?: string;
	evalResult?: string;
	error?: string;
}

export const browserTool: AgentTool<typeof browserSchema, BrowserDetails> = {
	name: "browser",
	label: "Browser",
	description:
		"Control a headless browser. Actions: navigate (url), click (x,y), type (text, optional selector), scroll (dy), back, screenshot, text (get page text), eval (run JS).",
	parameters: browserSchema,
	async execute(toolCallId, params, signal) {
		const { action, ...rest } = params;
		const endpoint =
			action === "navigate"
				? "/api/browser/navigate"
				: action === "click"
					? "/api/browser/click"
					: action === "type"
						? "/api/browser/type"
						: action === "scroll"
							? "/api/browser/scroll"
							: action === "back"
								? "/api/browser/back"
								: action === "screenshot"
									? "/api/browser/screenshot"
									: action === "text"
										? "/api/browser/text"
										: action === "eval"
											? "/api/browser/eval"
											: null;
		if (!endpoint) {
			return {
				content: [{ type: "text" as const, text: "Unknown action: " + action }],
				details: { action, error: "Unknown action" },
			};
		}
		try {
			const res = await fetch(TOOL_SERVER + endpoint, {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify(rest),
				signal,
			});
			const data = (await res.json()) as any;
			if (data.error) {
				return {
					content: [{ type: "text" as const, text: "Browser error: " + data.error }],
					details: { action, error: data.error },
				};
			}
			// Build text response for LLM
			const textParts: string[] = [];
			if (data.url) textParts.push("URL: " + data.url);
			if (data.title) textParts.push("Title: " + data.title);
			if (data.text) textParts.push("Page text:\n" + data.text);
			if (data.evalResult) textParts.push("Eval result: " + data.evalResult);
			if (data.screenshot) textParts.push("[Screenshot captured]");
			if (textParts.length === 0) textParts.push("Action completed.");
			// Include screenshot as image content if available
			const content: any[] = [{ type: "text" as const, text: textParts.join("\n") }];
			if (data.screenshot) {
				content.push({ type: "image" as const, mimeType: "image/jpeg", data: data.screenshot });
			}
			return {
				content,
				details: {
					action,
					url: data.url,
					title: data.title,
					screenshot: data.screenshot,
					text: data.text,
					evalResult: data.evalResult,
				},
			};
		} catch (err: any) {
			return {
				content: [{ type: "text" as const, text: "Browser tool error: " + err.message }],
				details: { action, error: err.message },
			};
		}
	},
};

class BrowserToolRenderer implements ToolRenderer<any, BrowserDetails> {
	render(params: any | undefined, result: ToolResultMessage<BrowserDetails> | undefined): ToolRenderResult {
		const state = result ? (result.isError ? "error" : "complete") : "inprogress";
		const action = result?.details?.action || params?.action || "...";
		const url = result?.details?.url || params?.url || "";
		const label = url ? action + ": " + url : action;
		if (result?.details?.screenshot) {
			return {
				content: html`
          <div class="flex flex-col gap-2">
            ${renderHeader(state, Globe, label)}
            <img src="data:image/jpeg;base64,${result.details.screenshot}"
                 class="rounded border border-border max-w-full" style="max-height:400px"
                 alt="Browser screenshot" />
            ${result.details.title ? html`<span class="text-xs text-muted-foreground">${result.details.title}</span>` : html``}
          </div>`,
				isCustom: false,
			};
		}
		if (result?.details?.text) {
			return {
				content: html`
          <div class="flex flex-col gap-2">
            ${renderHeader(state, Globe, label)}
            <pre class="text-xs p-3 rounded border border-border overflow-auto max-h-48 whitespace-pre-wrap">${result.details.text}</pre>
          </div>`,
				isCustom: false,
			};
		}
		return { content: renderHeader(state, Globe, label), isCustom: false };
	}
}

registerToolRenderer("browser", new BrowserToolRenderer());

export function createBrowserTool(): AgentTool<typeof browserSchema, BrowserDetails> {
	return browserTool;
}
