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 { Volume2 } from "lucide";
import { getAppStorage } from "../storage/app-storage.js";
import { registerToolRenderer, renderHeader } from "./renderer-registry.js";
import type { ToolRenderer, ToolRenderResult } from "./types.js";

const ttsSchema = Type.Object({
	text: Type.String({ description: "Text to convert to speech" }),
	model: Type.Optional(Type.String({ description: "Venice TTS model (default: tts-kokoro)" })),
	voice: Type.Optional(Type.String({ description: "Voice ID (default: af_heart)" })),
});

export interface TTSDetails {
	audioUrl?: string;
	model: string;
	voice: string;
	text: string;
	error?: string;
}

interface TTSParams {
	text: string;
	model?: string;
	voice?: string;
}

export const ttsTool: AgentTool<typeof ttsSchema, TTSDetails> = {
	name: "text_to_speech",
	label: "Text to Speech",
	description: "Convert text to speech using Venice AI TTS. Audio plays inline in chat.",
	parameters: ttsSchema,
	async execute(toolCallId, params, signal) {
		const { text, model = "tts-kokoro", voice = "af_heart" } = params;
		const apiKey = await getAppStorage().providerKeys.get("venice");
		if (!apiKey) {
			return {
				content: [{ type: "text", text: "Error: Venice API key not set." }],
				details: { model, voice, text, error: "No API key" },
			};
		}
		const res = await fetch("https://api.venice.ai/api/v1/audio/speech", {
			method: "POST",
			headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
			body: JSON.stringify({ model, input: text, voice }),
			signal: signal ?? AbortSignal.timeout(30000),
		});
		if (!res.ok) {
			const err = await res.text();
			return {
				content: [{ type: "text", text: `TTS failed (${res.status}): ${err}` }],
				details: { model, voice, text, error: err },
			};
		}
		const blob = await res.blob();
		const audioUrl = URL.createObjectURL(blob);
		return {
			content: [{ type: "text", text: `Speech generated. Model: ${model}, Voice: ${voice}` }],
			details: { audioUrl, model, voice, text },
		};
	},
};

class TTSRenderer implements ToolRenderer<TTSParams, TTSDetails> {
	render(params: TTSParams | undefined, result: ToolResultMessage<TTSDetails> | undefined): ToolRenderResult {
		const state = result ? (result.isError ? "error" : "complete") : "inprogress";
		if (result?.details?.audioUrl) {
			const d = result.details;
			return {
				content: html`
          <div class="flex flex-col gap-2">
            ${renderHeader(state, Volume2, "Speech Generated")}
            <audio controls src=${d.audioUrl} class="w-full"></audio>
            <div class="text-xs text-muted-foreground">${d.model} · ${d.voice}</div>
            <div class="text-xs text-foreground italic">${d.text.length > 100 ? d.text.slice(0, 100) + "..." : d.text}</div>
          </div>`,
				isCustom: false,
			};
		}
		return {
			content: renderHeader(state, Volume2, `Speaking: ${params?.text?.slice(0, 50) ?? "..."}`),
			isCustom: false,
		};
	}
}

registerToolRenderer("text_to_speech", new TTSRenderer());

export function createTTSTool(): AgentTool<typeof ttsSchema, TTSDetails> {
	return ttsTool;
}
