"use client";

import { useState, useEffect, useRef, useMemo, useCallback } from "react";
import Link from "next/link";
import { motion, useReducedMotion } from "motion/react";
import { MessageSquare, PhoneCall, PhoneOff, Send } from "lucide-react";
import { cn } from "@/lib/utils";
import type { IndustryMessage, IndustryCallTurn } from "@/content/industries";

interface IndustryHeroSimulatorProps {
  agentName: string;
  agentDescription: string;
  chatScript: IndustryMessage[];
  callScript: IndustryCallTurn[];
  audioSample?: string;
  primaryColorHex?: string;
}

/** Guards a possibly-undefined chat entry before it can reach the render map. */
function isMessage(m: IndustryMessage | undefined | null): m is IndustryMessage {
  return Boolean(m && typeof m.text === "string");
}

function isCallTurn(t: IndustryCallTurn | undefined | null): t is IndustryCallTurn {
  return Boolean(t && typeof t.text === "string");
}

export function IndustryHeroSimulator({
  agentName,
  agentDescription,
  chatScript,
  callScript,
}: IndustryHeroSimulatorProps) {
  const reduce = useReducedMotion();

  const [mode, setMode] = useState<"idle" | "chat" | "call">("idle");

  // Progression is driven by a BOUNDED count, never by pushing indexed
  // elements into an array. Rendering slices a pre-filtered dense array, so an
  // `undefined` message can never reach the map (the old crash's root cause).
  const [scriptCount, setScriptCount] = useState(0);
  const [customMessages, setCustomMessages] = useState<IndustryMessage[]>([]);
  const [awaitingReply, setAwaitingReply] = useState(false);

  const [callTurn, setCallTurn] = useState(0);
  const [callSeconds, setCallSeconds] = useState(0);
  const [isCalling, setIsCalling] = useState(false);

  const [userInput, setUserInput] = useState("");
  const threadRef = useRef<HTMLDivElement>(null);

  // Sanitise scripts once — anything malformed is filtered out here, upstream
  // of every consumer, so no downstream code has to trust the data shape.
  const safeChat = useMemo(
    () => (Array.isArray(chatScript) ? chatScript.filter(isMessage) : []),
    [chatScript],
  );
  const safeCall = useMemo(
    () => (Array.isArray(callScript) ? callScript.filter(isCallTurn) : []),
    [callScript],
  );

  const hasChat = safeChat.length > 0;
  const hasCall = safeCall.length > 0;

  // Visible chat = the revealed slice of the script + any user turns. Both parts
  // are dense arrays of defined messages by construction.
  const visibleChat = useMemo<IndustryMessage[]>(
    () => [...safeChat.slice(0, scriptCount), ...customMessages],
    [safeChat, scriptCount, customMessages],
  );

  const scriptDone = scriptCount >= safeChat.length;

  // Reveal scripted chat turns one at a time when entering chat mode.
  useEffect(() => {
    if (mode !== "chat" || !hasChat) return;

    // eslint-disable-next-line react-hooks/set-state-in-effect -- intentional: resets the scripted-chat reveal when entering chat mode (SSR-safe)
    setScriptCount(1);
    setCustomMessages([]);
    setAwaitingReply(false);

    // Reduced motion: show the whole exchange at once, no timed reveal.
    if (reduce) {
      setScriptCount(safeChat.length);
      return;
    }

    const id = window.setInterval(() => {
      setScriptCount((count) => {
        const next = count + 1;
        if (next >= safeChat.length) window.clearInterval(id);
        return Math.min(next, safeChat.length);
      });
    }, 1500);

    return () => window.clearInterval(id);
  }, [mode, hasChat, safeChat, reduce]);

  // Call timer.
  useEffect(() => {
    if (mode !== "call" || !isCalling) return;
    const id = window.setInterval(() => setCallSeconds((s) => s + 1), 1000);
    return () => window.clearInterval(id);
  }, [mode, isCalling]);

  // Call transcript progression (bounded by modulo on a guaranteed-positive len).
  useEffect(() => {
    if (mode !== "call" || !isCalling || !hasCall) return;
    const id = window.setInterval(() => {
      setCallTurn((prev) => (prev + 1) % safeCall.length);
    }, 4000);
    return () => window.clearInterval(id);
  }, [mode, isCalling, hasCall, safeCall.length]);

  // Keep the newest message in view.
  useEffect(() => {
    const el = threadRef.current;
    if (el) el.scrollTo({ top: el.scrollHeight, behavior: reduce ? "auto" : "smooth" });
  }, [visibleChat.length, awaitingReply, reduce]);

  const openChat = useCallback(() => setMode("chat"), []);

  const startCall = useCallback(() => {
    setMode("call");
    setIsCalling(true);
    setCallSeconds(0);
    setCallTurn(0);
  }, []);

  const endCall = useCallback(() => {
    setIsCalling(false);
    setMode("idle");
  }, []);

  const closeChat = useCallback(() => setMode("idle"), []);

  const sendCustom = useCallback(
    (e: React.FormEvent) => {
      e.preventDefault();
      const text = userInput.trim();
      if (!text) return;
      setCustomMessages((prev) => [...prev, { from: "user", text }]);
      setUserInput("");
      setAwaitingReply(true);
      window.setTimeout(() => {
        setCustomMessages((prev) => [
          ...prev,
          {
            from: "agent",
            text: "Thanks! This is a scripted preview of how the agent replies — book a call and we'll tailor a live demo to your exact workflow.",
          },
        ]);
        setAwaitingReply(false);
      }, 1100);
    },
    [userInput],
  );

  const showTyping = mode === "chat" && (awaitingReply || (!scriptDone && hasChat));

  return (
    <div className="relative mx-auto w-full">
      <div className="relative overflow-hidden rounded-3xl border border-border/80 bg-gradient-to-b from-secondary/30 via-background to-secondary/20 p-6 sm:p-12 shadow-xl">
        {/* Subtle radial halftone grid */}
        <div
          aria-hidden
          className="pointer-events-none absolute inset-0 opacity-25"
          style={{
            backgroundImage: "radial-gradient(circle, currentColor 1.2px, transparent 1.2px)",
            backgroundSize: "20px 20px",
          }}
        />

        <div className="relative z-10 mx-auto max-w-lg">
          {/* Modes swap instantly (no exit-blocked transition) and animate in. */}
          <>
            {/* MODE: idle */}
            {mode === "idle" && (
              <motion.div
                key="idle"
                initial={reduce ? false : { opacity: 0, y: 12, scale: 0.98 }}
                animate={{ opacity: 1, y: 0, scale: 1 }}
                transition={{ duration: 0.32, ease: [0.22, 1, 0.36, 1] }}
                className="rounded-3xl border border-border/80 bg-card/95 p-8 text-center shadow-2xl backdrop-blur-md"
              >
                <motion.div
                  aria-hidden
                  animate={reduce ? undefined : { y: [0, -5, 0] }}
                  transition={{ duration: 4, repeat: Infinity, ease: "easeInOut" }}
                  className="relative mx-auto flex size-16 items-center justify-center rounded-2xl bg-primary text-primary-foreground shadow-md"
                >
                  <span className="font-display text-2xl font-bold tracking-tight">Q</span>
                  {!reduce && (
                    <motion.span
                      className="absolute inset-0 rounded-2xl ring-1 ring-primary/40"
                      animate={{ opacity: [0.5, 0, 0.5], scale: [1, 1.18, 1] }}
                      transition={{ duration: 3, repeat: Infinity, ease: "easeInOut" }}
                    />
                  )}
                </motion.div>

                <h3 className="mt-5 font-display text-xl font-bold tracking-tight text-foreground">
                  {agentName}
                </h3>
                <p className="mt-2 text-sm leading-relaxed text-muted-foreground">
                  {agentDescription}
                </p>

                <div className="mt-6 flex flex-col items-stretch justify-center gap-3 sm:flex-row sm:items-center">
                  <motion.button
                    type="button"
                    onClick={openChat}
                    whileHover={reduce ? undefined : { scale: 1.03 }}
                    whileTap={reduce ? undefined : { scale: 0.97 }}
                    className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-foreground px-6 text-sm font-semibold text-background shadow-sm transition-colors hover:bg-foreground/90 sm:w-auto"
                  >
                    <MessageSquare className="size-4" />
                    <span>Chat</span>
                  </motion.button>

                  <motion.button
                    type="button"
                    onClick={startCall}
                    whileHover={reduce ? undefined : { scale: 1.03 }}
                    whileTap={reduce ? undefined : { scale: 0.97 }}
                    className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-xl bg-primary px-6 text-sm font-semibold text-primary-foreground shadow-sm transition-colors hover:bg-primary/90 sm:w-auto"
                  >
                    <PhoneCall className="size-4" />
                    <span>Call</span>
                  </motion.button>
                </div>

                <p className="mt-6 text-[11px] text-muted-foreground/80">
                  By continuing, you agree to our{" "}
                  <Link href="/privacy" className="underline hover:text-foreground">
                    Privacy Policy
                  </Link>{" "}
                  and{" "}
                  <Link href="/terms" className="underline hover:text-foreground">
                    T&amp;C
                  </Link>
                  .
                </p>
              </motion.div>
            )}

            {/* MODE: chat */}
            {mode === "chat" && (
              <motion.div
                key="chat"
                initial={reduce ? false : { opacity: 0, y: 12, scale: 0.98 }}
                animate={{ opacity: 1, y: 0, scale: 1 }}
                transition={{ duration: 0.32, ease: [0.22, 1, 0.36, 1] }}
                className="flex h-[min(430px,72vh)] min-h-[360px] flex-col overflow-hidden rounded-3xl border border-border/80 bg-card shadow-2xl"
              >
                <div className="flex items-center justify-between border-b border-border/60 bg-secondary/30 px-5 py-3.5">
                  <div className="flex items-center gap-3">
                    <div className="flex size-8 items-center justify-center rounded-full bg-primary text-xs font-bold text-primary-foreground">
                      Q
                    </div>
                    <div>
                      <h4 className="text-xs font-bold text-foreground">{agentName}</h4>
                      <span className="flex items-center gap-1 text-[10px] font-medium text-muted-foreground">
                        <span className="size-1.5 rounded-full bg-primary animate-pulse" />
                        Active Agent
                      </span>
                    </div>
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="rounded-full border border-border/60 bg-background px-2 py-0.5 text-[9px] font-semibold uppercase tracking-wider text-muted-foreground">
                      Demo
                    </span>
                    <button
                      type="button"
                      onClick={closeChat}
                      className="rounded-lg px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground"
                    >
                      Close
                    </button>
                  </div>
                </div>

                <div ref={threadRef} className="flex-1 space-y-3 overflow-y-auto p-4 text-xs">
                  {hasChat ? (
                    <>
                      {visibleChat.map((msg, idx) => (
                        <motion.div
                          key={idx}
                          initial={reduce ? false : { opacity: 0, y: 8 }}
                          animate={{ opacity: 1, y: 0 }}
                          transition={{ duration: 0.28, ease: "easeOut" }}
                          className={cn(
                            "flex max-w-[82%] flex-col rounded-2xl px-3.5 py-2.5 leading-relaxed shadow-xs",
                            msg.from === "user"
                              ? "ml-auto rounded-br-xs bg-primary text-primary-foreground"
                              : "mr-auto rounded-bl-xs border border-border/60 bg-secondary/60 text-foreground",
                          )}
                        >
                          <span>{msg.text}</span>
                          {msg.time && (
                            <span
                              className={cn(
                                "mt-1 self-end text-[9px]",
                                msg.from === "user"
                                  ? "text-primary-foreground/70"
                                  : "text-muted-foreground",
                              )}
                            >
                              {msg.time}
                            </span>
                          )}
                        </motion.div>
                      ))}
                      {showTyping && (
                        <motion.div
                          initial={reduce ? false : { opacity: 0 }}
                          animate={{ opacity: 1 }}
                          className="mr-auto flex items-center gap-1 rounded-2xl rounded-bl-xs border border-border/60 bg-secondary/60 px-3.5 py-3"
                          aria-label="Agent is typing"
                        >
                          {[0, 1, 2].map((d) => (
                            <motion.span
                              key={d}
                              className="size-1.5 rounded-full bg-muted-foreground"
                              animate={reduce ? undefined : { opacity: [0.3, 1, 0.3], y: [0, -2, 0] }}
                              transition={{ duration: 1, repeat: Infinity, delay: d * 0.15 }}
                            />
                          ))}
                        </motion.div>
                      )}
                    </>
                  ) : (
                    <div className="flex h-full flex-col items-center justify-center gap-2 text-center text-muted-foreground">
                      <MessageSquare className="size-6 opacity-40" />
                      <p className="text-xs">
                        A live chat demo isn&apos;t available for this agent yet.
                      </p>
                      <Link
                        href="/contact"
                        className="text-xs font-semibold text-foreground underline"
                      >
                        Book a call instead
                      </Link>
                    </div>
                  )}
                </div>

                <form
                  onSubmit={sendCustom}
                  className="flex items-center gap-2 border-t border-border/60 bg-secondary/10 p-3"
                >
                  <input
                    type="text"
                    value={userInput}
                    onChange={(e) => setUserInput(e.target.value)}
                    placeholder="Type a response to test the agent…"
                    aria-label="Type a message to the demo agent"
                    className="flex-1 rounded-xl border border-border/60 bg-background px-3.5 py-2 text-xs text-foreground placeholder:text-muted-foreground focus:outline-hidden focus:ring-1 focus:ring-primary"
                  />
                  <motion.button
                    type="submit"
                    whileTap={reduce ? undefined : { scale: 0.9 }}
                    className="flex size-8 items-center justify-center rounded-xl bg-primary text-primary-foreground transition-colors hover:bg-primary/90"
                    aria-label="Send message"
                  >
                    <Send className="size-3.5" />
                  </motion.button>
                </form>
              </motion.div>
            )}

            {/* MODE: call */}
            {mode === "call" && (
              <motion.div
                key="call"
                initial={reduce ? false : { opacity: 0, y: 12, scale: 0.98 }}
                animate={{ opacity: 1, y: 0, scale: 1 }}
                transition={{ duration: 0.32, ease: [0.22, 1, 0.36, 1] }}
                className="flex min-h-[340px] flex-col items-center justify-between rounded-3xl border border-white/10 bg-neutral-950 p-6 text-white shadow-2xl sm:min-h-[380px] sm:p-8"
              >
                <div className="flex w-full items-center justify-between text-xs text-neutral-400">
                  <span className="flex items-center gap-1.5 font-mono">
                    <span className="size-2 rounded-full bg-white animate-ping" />
                    00:{callSeconds < 10 ? `0${callSeconds}` : callSeconds}
                  </span>
                  <span className="rounded-full bg-neutral-800 px-2.5 py-0.5 text-[10px] font-semibold uppercase text-neutral-300">
                    Demo · Voice Stream
                  </span>
                </div>

                <div className="my-6 flex flex-col items-center text-center">
                  <motion.div
                    className="relative flex size-20 items-center justify-center rounded-full bg-white/10 shadow-lg ring-4 ring-white/10"
                    animate={reduce ? undefined : { scale: [1, 1.05, 1] }}
                    transition={{ duration: 1.8, repeat: Infinity, ease: "easeInOut" }}
                  >
                    <span className="font-display text-2xl font-bold text-white">Q</span>
                  </motion.div>
                  <h4 className="mt-3 font-display text-lg font-bold text-white">{agentName}</h4>
                  <p className="text-xs text-neutral-400">Simulated real-time conversation</p>

                  <div className="mt-5 flex h-8 items-center justify-center gap-0.5 sm:gap-1">
                    {Array.from({ length: 24 }).map((_, i) => (
                      <span
                        key={i}
                        className="min-w-0 flex-1 rounded-full bg-white/70 transition-all duration-150 sm:w-1 sm:flex-none"
                        style={{
                          height: `${Math.max(15, Math.abs(Math.sin((callSeconds * 4 + i) * 0.5)) * 100)}%`,
                          opacity: 0.6 + (i % 5) * 0.08,
                        }}
                      />
                    ))}
                  </div>
                </div>

                <div className="w-full rounded-2xl border border-neutral-800 bg-neutral-900/90 p-3 text-center">
                  {hasCall ? (
                    <>
                      <span className="block text-[10px] font-bold uppercase tracking-wider text-neutral-400">
                        {safeCall[callTurn]?.speaker ?? "Agent"}
                      </span>
                      <p className="mt-0.5 line-clamp-2 text-xs text-neutral-200">
                        &ldquo;{safeCall[callTurn]?.text ?? ""}&rdquo;
                      </p>
                    </>
                  ) : (
                    <p className="text-xs text-neutral-300">
                      Connecting you to a live demo — no sample script for this agent yet.
                    </p>
                  )}
                </div>

                <div className="mt-6 flex items-center justify-center">
                  <motion.button
                    type="button"
                    onClick={endCall}
                    whileHover={reduce ? undefined : { scale: 1.08 }}
                    whileTap={reduce ? undefined : { scale: 0.92 }}
                    className="flex size-12 items-center justify-center rounded-full bg-white text-neutral-900 shadow-lg"
                    aria-label="End call"
                  >
                    <PhoneOff className="size-5" />
                  </motion.button>
                </div>
              </motion.div>
            )}
          </>
        </div>
      </div>
    </div>
  );
}
