/**
 * VectorDrive Search Tool
 *
 * Semantic search over stored vectors. Accepts a pre-computed query vector
 * or raw text (auto-embedded). Falls back to metadata keyword matching
 * when vectordrive is offline.
 */

import { Type } from "@sinclair/typebox";
import type { ExtensionAPI } from "@singularity-forge/pi-coding-agent";
import { VectordriveManager, textToVector } from "./manager.js";

export interface ToolExecutionResult {
	content: Array<{ type: "text"; text: string }>;
	details: Record<string, unknown>;
	isError?: boolean;
}

export function registerVectordriveSearchTool(pi: ExtensionAPI): void {
	pi.registerTool({
		name: "vectordrive_search",
		label: "VectorDrive Search",
		description:
			"Search VectorDrive by vector similarity or text query. " +
			"Returns the most relevant stored entries with similarity scores. " +
			"When no embedding model is available, a simple hash embedding is used — " +
			"for best results provide pre-computed vectors via vectordrive_store.",
		promptSnippet: "Search VectorDrive memories or code chunks",
		promptGuidelines: [
			"Use vectordrive_search to find previously stored memories, code chunks, or documents.",
			"Be specific with queries for better results.",
			"If you stored code with metadata.file_path, results will include the source location.",
		],
		parameters: Type.Object({
			query: Type.String({
				description: "Text query to search for (auto-converted to embedding)",
			}),
			vector: Type.Optional(
				Type.Array(Type.Number(), {
					description: "Optional pre-computed query vector. If provided, overrides 'query' text.",
				}),
			),
			limit: Type.Optional(
				Type.Number({
					default: 10,
					description: "Maximum results (1-50)",
					minimum: 1,
					maximum: 50,
				}),
			),
		}),
		async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
			const manager = VectordriveManager.getInstance();
			const status = await manager.getStatus();
			const limit = Math.min(Math.max(params.limit ?? 10, 1), 50);

			if (status.backend === "none") {
				return {
					content: [
						{
							type: "text",
							text: `VectorDrive is unavailable: ${status.error ?? "unknown error"}\n\nInstall with: npm install vectordrive`,
						},
					],
					details: { status },
					isError: true,
				};
			}

			const queryVector =
				params.vector && params.vector.length > 0
					? params.vector
					: textToVector(params.query);

			const results = await manager.search(queryVector, limit);

			if (results.length === 0) {
				return {
					content: [
						{
							type: "text",
							text: `No results found in VectorDrive for query: "${params.query}"`,
						},
					],
					details: { query: params.query, count: 0 },
					isError: false,
				};
			}

			const lines: string[] = [];
			lines.push(`# VectorDrive Search Results`);
			lines.push(`Query: "${params.query}"`);
			lines.push("");

			for (const r of results) {
				const meta = r.metadata ?? {};
				const preview = meta.text_preview ?? "";
				lines.push(`## ${r.id} (score: ${r.score.toFixed(4)})`);
				if (preview) {
					lines.push("```");
					lines.push(String(preview).slice(0, 400));
					lines.push("```");
				}
				const metaLines = Object.entries(meta)
					.filter(([k]) => k !== "text_preview" && k !== "stored_at")
					.map(([k, v]) => `- ${k}: ${v}`);
				if (metaLines.length > 0) {
					lines.push(...metaLines);
				}
				lines.push("");
			}

			return {
				content: [{ type: "text", text: lines.join("\n") }],
				details: { results, count: results.length },
				isError: false,
			};
		},
	});
}
