import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Volume2, VolumeX, Loader2, Captions } from "lucide-react";

import host from "@/assets/ai-host.jpg.asset.json";
import { useReducedMotion } from "@/hooks/use-reduced-motion";

const GREETING =
  "Welcome to Gatavase Corporation. I am your Gatavase A I host. Step into the universe of intelligent systems — A I platforms, secure messaging, search and enterprise software, engineered in Kampala and Doha for the world.";

/**
 * Holographic AI head that greets every visitor with a spoken welcome.
 * Audio is generated server-side; browser speech synthesis is the fallback.
 */
export function HoloHost({ text = GREETING }: { text?: string }) {
  const reduced = useReducedMotion();
  const [state, setState] = useState<"idle" | "loading" | "speaking">("idle");
  const [level, setLevel] = useState(0);
  const [muted, setMuted] = useState(false);
  const [captions, setCaptions] = useState(true);
  const [cueIndex, setCueIndex] = useState(0);
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const rafRef = useRef<number | null>(null);

  const cues = useMemo(
    () => text.split(/(?<=[.!?—])\s+/).filter(Boolean),
    [text],
  );

  // Advance the caption cue roughly in time with the spoken greeting.
  useEffect(() => {
    if (state !== "speaking") {
      setCueIndex(0);
      return;
    }
    let i = 0;
    setCueIndex(0);
    const timers: number[] = [];
    let elapsed = 0;
    for (const cue of cues) {
      const index = i++;
      timers.push(window.setTimeout(() => setCueIndex(index), elapsed));
      elapsed += Math.max(1600, (cue.split(/\s+/).length / 2.6) * 1000);
    }
    return () => timers.forEach((t) => window.clearTimeout(t));
  }, [state, cues]);


  const stop = useCallback(() => {
    if (rafRef.current) cancelAnimationFrame(rafRef.current);
    rafRef.current = null;
    if (audioRef.current) {
      audioRef.current.pause();
      audioRef.current = null;
    }
    if (typeof window !== "undefined") window.speechSynthesis?.cancel();
    setState("idle");
    setLevel(0);
  }, []);

  const speak = useCallback(async () => {
    stop();
    setState("loading");
    try {
      const res = await fetch("/api/tts", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ text }),
      });
      if (!res.ok) throw new Error(String(res.status));
      const blob = await res.blob();
      const audio = new Audio(URL.createObjectURL(blob));
      audioRef.current = audio;

      let analyser: AnalyserNode | null = null;
      try {
        const ctx = new AudioContext();
        if (ctx.state === "suspended") await ctx.resume().catch(() => {});
        const src = ctx.createMediaElementSource(audio);
        analyser = ctx.createAnalyser();
        analyser.fftSize = 256;
        src.connect(analyser);
        analyser.connect(ctx.destination);
      } catch {
        analyser = null;
      }

      audio.onended = () => stop();
      await audio.play();
      setState("speaking");

      const data = analyser ? new Uint8Array(analyser.frequencyBinCount) : null;
      const tick = () => {
        if (analyser && data) {
          analyser.getByteFrequencyData(data);
          const avg = data.reduce((a, b) => a + b, 0) / data.length;
          setLevel(Math.min(1, avg / 90));
        } else {
          setLevel(0.35 + Math.sin(Date.now() / 110) * 0.3);
        }
        rafRef.current = requestAnimationFrame(tick);
      };
      rafRef.current = requestAnimationFrame(tick);
    } catch {
      // Fallback: browser speech synthesis
      if (typeof window !== "undefined" && window.speechSynthesis) {
        const utter = new SpeechSynthesisUtterance(text);
        utter.rate = 0.95;
        utter.pitch = 0.9;
        utter.onend = () => stop();
        window.speechSynthesis.speak(utter);
        setState("speaking");
        const tick = () => {
          setLevel(0.35 + Math.sin(Date.now() / 110) * 0.3);
          rafRef.current = requestAnimationFrame(tick);
        };
        rafRef.current = requestAnimationFrame(tick);
      } else {
        setState("idle");
      }
    }
  }, [stop, text]);

  // Greet on every visit; browsers may block autoplay until the first gesture.
  useEffect(() => {
    if (muted) return;
    let cancelled = false;
    const greet = () => {
      if (!cancelled) void speak();
    };
    const timer = window.setTimeout(greet, 900);
    const onGesture = () => {
      if (!audioRef.current && state === "idle") greet();
      window.removeEventListener("pointerdown", onGesture);
    };
    window.addEventListener("pointerdown", onGesture, { once: true });
    return () => {
      cancelled = true;
      window.clearTimeout(timer);
      window.removeEventListener("pointerdown", onGesture);
      stop();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const glow = state === "speaking" ? level : 0;

  return (
    <div className="relative mx-auto w-full max-w-sm">
      {/* holo rings */}
      <div
        className="pointer-events-none absolute inset-0 -z-10 rounded-full blur-3xl"
        style={{
          background:
            "radial-gradient(circle at 50% 45%, color-mix(in oklab, var(--primary) 45%, transparent), transparent 65%)",
          opacity: 0.35 + glow * 0.5,
        }}
      />
      <div className="relative aspect-square overflow-hidden rounded-full border border-primary/40 bg-primary/5">
        <img
          src={host.url}
          alt="Gatavase AI holographic host"
          className="size-full scale-110 object-cover"
          style={{
            filter: `grayscale(1) sepia(1) hue-rotate(150deg) saturate(${2.4 + glow * 1.6}) contrast(${1.1 + glow * 0.25}) brightness(${0.85 + glow * 0.3})`,
            mixBlendMode: "screen",
          }}
        />
        {/* scanlines */}
        <div
          className="pointer-events-none absolute inset-0 opacity-40"
          style={{
            backgroundImage:
              "repeating-linear-gradient(to bottom, color-mix(in oklab, var(--primary) 30%, transparent) 0 1px, transparent 1px 4px)",
            animation: reduced ? undefined : "holo-scan 6s linear infinite",
          }}
        />
        {/* voice wave */}
        <div className="pointer-events-none absolute inset-x-8 bottom-6 flex items-end justify-center gap-1">
          {Array.from({ length: 18 }).map((_, i) => (
            <span
              key={i}
              className="w-1 rounded-full bg-primary"
              style={{
                height: `${6 + Math.abs(Math.sin(i * 0.8)) * glow * 46}px`,
                opacity: 0.35 + glow * 0.65,
                transition: "height 90ms linear",
              }}
            />
          ))}
        </div>
      </div>

      <div className="mt-6 flex items-center justify-center gap-2">
        <button
          onClick={() => (state === "speaking" ? stop() : void speak())}
          className="inline-flex items-center gap-2 rounded-full border border-primary/40 bg-primary/10 px-4 py-2 text-sm font-medium text-primary transition-colors hover:bg-primary/20"
        >
          {state === "loading" ? (
            <Loader2 className="size-4 animate-spin" />
          ) : (
            <Volume2 className="size-4" />
          )}
          {state === "speaking" ? "Stop hologram" : "Hear the welcome"}
        </button>
        <button
          onClick={() => {
            setMuted((m) => !m);
            stop();
          }}
          aria-label={muted ? "Unmute host" : "Mute host"}
          className="grid size-9 place-items-center rounded-full border border-border text-muted-foreground transition-colors hover:text-foreground"
        >
          {muted ? <VolumeX className="size-4" /> : <Volume2 className="size-4" />}
        </button>
      </div>
      <p className="mt-3 text-center text-xs text-muted-foreground">
        {state === "speaking" ? "Hologram speaking…" : "Gatavase AI host · voice greeting"}
      </p>

      {/* On-screen captions for the spoken greeting */}
      <div className="mt-4 flex items-center justify-center">
        <button
          onClick={() => setCaptions((c) => !c)}
          aria-pressed={captions}
          className="inline-flex items-center gap-2 rounded-full border border-border px-3 py-1 text-[11px] font-mono uppercase tracking-widest text-muted-foreground hover:text-foreground"
        >
          <Captions className="size-3.5" /> {captions ? "Captions on" : "Captions off"}
        </button>
      </div>
      {captions && (
        <div
          aria-live="polite"
          className="mt-3 rounded-2xl border border-primary/25 bg-background/70 px-4 py-3 text-center text-sm leading-relaxed backdrop-blur"
        >
          {cues.map((cue, i) => (
            <span
              key={i}
              className={
                state === "speaking" && i === cueIndex
                  ? "text-foreground"
                  : "text-muted-foreground/70"
              }
            >
              {cue}{" "}
            </span>
          ))}
        </div>
      )}

    </div>
  );
}
