import { createFileRoute } from "@tanstack/react-router";
import { useState } from "react";
import { PageShell } from "@/components/page-shell";
import { toolSeo } from "@/lib/tool-seo";
import { authedFetch } from "@/lib/authed-fetch";

export const Route = createFileRoute("/tools/voice-cloning")({
  head: () =>
    toolSeo({
      path: "/tools/voice-cloning",
      title: "AI Voice Cloning — Clone Any Voice from a Short Sample | Gatavase AI Creative",
      shortTitle: "Voice Cloning — Gatavase AI Creative",
      description:
        "Clone any voice from short audio samples with ElevenLabs-powered AI on Gatavase AI Creative. Upload thirty seconds to a few minutes of clean speech, name your voice, and generate lifelike narration, dubbing, audiobooks and podcasts in that voice. Built in Uganda by Gatavase Corporation to empower African storytellers, educators and creators to preserve local voices, produce content in mother tongues, and scale multilingual audio for radio, film, e-learning and social media across the continent.",
      ogDescription: "Upload a sample and generate a cloned voice for podcasts, audiobooks and dubbing.",
      category: "MultimediaApplication",
    }),
  component: VoiceCloningPage,
});

function VoiceCloningPage() {
  const [name, setName] = useState("");
  const [description, setDescription] = useState("");
  const [files, setFiles] = useState<File[]>([]);
  const [status, setStatus] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [clonedVoiceId, setClonedVoiceId] = useState<string | null>(null);
  const [testText, setTestText] = useState("Muraho! This is my Gatavase-cloned voice, speaking from Kampala.");
  const [audioUrl, setAudioUrl] = useState<string | null>(null);
  const [speaking, setSpeaking] = useState(false);

  const submit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null); setStatus(null); setClonedVoiceId(null); setAudioUrl(null);
    if (!name.trim()) { setError("Give your voice a name."); return; }
    if (files.length === 0) { setError("Upload at least one audio sample."); return; }
    setLoading(true);
    try {
      const fd = new FormData();
      fd.append("name", name);
      if (description) fd.append("description", description);
      for (const f of files) fd.append("files", f, f.name);
      const res = await authedFetch("/api/elevenlabs/clone", { method: "POST", body: fd });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error ?? "Cloning failed");
      setClonedVoiceId(data.voiceId);
      setStatus(`Voice "${data.name}" cloned successfully. Voice ID: ${data.voiceId}`);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Cloning failed");
    } finally { setLoading(false); }
  };

  const speak = async () => {
    if (!clonedVoiceId || !testText.trim()) return;
    setSpeaking(true); setError(null); setAudioUrl(null);
    try {
      const res = await authedFetch("/api/elevenlabs/tts", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ text: testText, voiceId: clonedVoiceId }),
      });
      if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error ?? `TTS failed [${res.status}]`);
      const blob = await res.blob();
      setAudioUrl(URL.createObjectURL(blob));
    } catch (err) {
      setError(err instanceof Error ? err.message : "TTS failed");
    } finally { setSpeaking(false); }
  };

  return (
    <PageShell
      eyebrow="Multimedia · Voice Cloning"
      title="Voice Cloning"
      lead="Upload a clean audio sample (30 s – a few minutes). We'll clone the voice with ElevenLabs so you can narrate podcasts, audiobooks and dubbing in it."
    >
      <form onSubmit={submit} className="glow-card grid gap-4 rounded-2xl p-6">
        <div>
          <label className="mb-1 block text-sm font-medium">Voice name</label>
          <input value={name} onChange={(e) => setName(e.target.value)}
            placeholder="e.g. Naiga Storyteller"
            className="w-full rounded-lg border border-border bg-input px-3 py-2 text-sm outline-none focus:border-primary" />
        </div>
        <div>
          <label className="mb-1 block text-sm font-medium">Description (optional)</label>
          <input value={description} onChange={(e) => setDescription(e.target.value)}
            placeholder="Warm Ugandan narrator, mid-30s"
            className="w-full rounded-lg border border-border bg-input px-3 py-2 text-sm outline-none focus:border-primary" />
        </div>
        <div>
          <label className="mb-1 block text-sm font-medium">Audio samples (mp3 / wav / m4a)</label>
          <input type="file" accept="audio/*" multiple
            onChange={(e) => setFiles(Array.from(e.target.files ?? []))}
            className="block w-full text-sm text-muted-foreground file:mr-4 file:rounded-lg file:border-0 file:bg-primary file:px-4 file:py-2 file:text-primary-foreground" />
          {files.length > 0 && (
            <div className="mt-2 text-xs text-muted-foreground">{files.length} file(s) selected</div>
          )}
        </div>
        <button type="submit" disabled={loading}
          className="w-full rounded-lg bg-primary px-4 py-2.5 text-sm font-medium text-primary-foreground disabled:opacity-50">
          {loading ? "Cloning voice…" : "Clone voice"}
        </button>
        {status && <div className="rounded-lg border border-primary/40 bg-primary/10 px-3 py-2 text-sm">{status}</div>}
        {error && <div className="rounded-lg border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive">{error}</div>}
      </form>

      {clonedVoiceId && (
        <div className="glow-card mt-6 rounded-2xl p-6">
          <h3 className="font-display text-xl font-semibold">Test your cloned voice</h3>
          <textarea rows={4} value={testText} onChange={(e) => setTestText(e.target.value)}
            className="mt-3 w-full resize-none rounded-lg border border-border bg-input px-3 py-2 text-sm outline-none focus:border-primary" />
          <button onClick={speak} disabled={speaking}
            className="mt-3 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground disabled:opacity-50">
            {speaking ? "Generating…" : "Speak with cloned voice"}
          </button>
          {audioUrl && (
            <div className="mt-4">
              <audio controls src={audioUrl} className="w-full" />
              <a href={audioUrl} download="gatavase-cloned-voice.mp3"
                className="mt-2 inline-block text-sm text-primary underline">Download MP3</a>
            </div>
          )}
        </div>
      )}
    </PageShell>
  );
}
