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 { Terminal } 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 bashSchema = Type.Object({
	command: Type.String({ description: "Shell command to execute" }),
	timeout: Type.Optional(Type.Number({ description: "Timeout in ms (default: 30000)" })),
});

export interface BashDetails {
	stdout: string;
	stderr: string;
	exitCode: number;
	command: string;
}

export const bashTool: AgentTool<typeof bashSchema, BashDetails> = {
	name: "bash",
	label: "Terminal",
	description:
		"Execute a shell command on the server. Use for file operations, installing packages, running scripts, git commands, etc.",
	parameters: bashSchema,
	async execute(toolCallId, params, signal) {
		const { command, timeout = 30000 } = params;
		try {
			const res = await fetch(TOOL_SERVER + "/api/bash", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ command, timeout }),
				signal,
			});
			const data = (await res.json()) as any;
			if (data.error) {
				return {
					content: [{ type: "text" as const, text: "Error: " + data.error }],
					details: { stdout: "", stderr: data.error, exitCode: 1, command },
				};
			}
			const output = data.output || data.stdout || "";
			return {
				content: [{ type: "text" as const, text: output.slice(0, 10000) || "(no output)" }],
				details: { stdout: data.stdout, stderr: data.stderr, exitCode: data.exitCode, command },
			};
		} catch (err: any) {
			return {
				content: [{ type: "text" as const, text: "Bash tool error: " + err.message }],
				details: { stdout: "", stderr: err.message, exitCode: 1, command },
			};
		}
	},
};

class BashToolRenderer implements ToolRenderer<{ command: string }, BashDetails> {
	render(
		params: { command: string } | undefined,
		result: ToolResultMessage<BashDetails> | undefined,
	): ToolRenderResult {
		const state = result ? (result.isError ? "error" : "complete") : "inprogress";
		const cmd = result?.details?.command || params?.command || "...";
		const exitCode = result?.details?.exitCode;
		const icon = state === "error" ? "text-red-500" : exitCode === 0 ? "text-green-500" : "";
		if (result?.details) {
			const d = result.details;
			return {
				content: html`
          <div class="flex flex-col gap-2">
            ${renderHeader(state, Terminal, "$ " + cmd)}
            <pre class="text-xs bg-black text-green-400 p-3 rounded overflow-auto max-h-64 whitespace-pre-wrap font-mono">${d.stdout}${d.stderr ? "\nSTDERR: " + d.stderr : ""}</pre>
            <span class="text-xs ${icon}">Exit code: ${d.exitCode}</span>
          </div>`,
				isCustom: false,
			};
		}
		return { content: renderHeader(state, Terminal, "$ " + cmd), isCustom: false };
	}
}

registerToolRenderer("bash", new BashToolRenderer());

export function createBashTool(): AgentTool<typeof bashSchema, BashDetails> {
	return bashTool;
}
