/* global React */
// IamaiMascot — drop-in React component for the IAMAI agent mascot.
//
// Props:
//   state          : "idle" | "thinking" | "speaking" | "success"   (default: "idle")
//   eyeTracking    : boolean — eyes follow the cursor                (default: true)
//   blinkTrigger   : any — any change in this value triggers a quick blink
//   size           : number — pixel size (square)                    (default: 320)
//   tone           : "cool" | "neutral" | "warm" — studio bg tint    (default: "cool")
//   showBg         : boolean — draw the studio background + halo     (default: true)
//   className, style — passthroughs
//
// Imperative: also dispatches/listens for the custom event "iamai:blink"
// on the wrapper element so plain JS can trigger a blink:
//   el.dispatchEvent(new CustomEvent('iamai:blink'))
// ============================================================

const { useEffect, useRef, useState, useMemo } = React;

// ─── geometry constants ───────────────────────────────────────
// The whole mascot draws into a 1000×1000 viewBox.
// Head squircle bbox after translate (290, 200) and our internal coords:
//   head local box: 60..340 x 60..340  → after translate 350..630 x 260..540
// Eye centers (in head local coords): left (161, 200), right (239, 200)
// In viewBox coords with translate(290,200) + scale(1.15) about... we keep it simple:
// We'll build the head INLINE here so we have direct DOM refs to the eyes.

function StudioBg({ tone = "cool" }) {
  const grads = {
    neutral: { a: "#f4f5f8", b: "#e3e7ee", c: "#cdd2dc" },
    cool:    { a: "#f0f4fb", b: "#dde6f4", c: "#c2cee2" },
    warm:    { a: "#f7f5f1", b: "#ece7df", c: "#d4ccbf" },
  };
  const g = grads[tone] || grads.cool;
  return (
    <g>
      <defs>
        <radialGradient id={`iamai-bg-${tone}`} cx="50%" cy="35%" r="85%">
          <stop offset="0%"  stopColor={g.a} />
          <stop offset="55%" stopColor={g.b} />
          <stop offset="100%" stopColor={g.c} />
        </radialGradient>
      </defs>
      <rect x="0" y="0" width="1000" height="1000" fill={`url(#iamai-bg-${tone})`} />
    </g>
  );
}

// ─── the mascot itself ───────────────────────────────────────
function IamaiMascot({
  state = "idle",
  eyeTracking = true,
  blinkTrigger,
  size = 320,
  tone = "cool",
  showBg = true,
  className = "",
  style = {},
}) {
  const wrapRef = useRef(null);
  const leftEyeRef = useRef(null);
  const rightEyeRef = useRef(null);
  const [eyeOffset, setEyeOffset] = useState({ x: 0, y: 0 });
  const [blink, setBlink] = useState(false);

  // ─ Cursor tracking ─
  useEffect(() => {
    if (!eyeTracking) return;
    const onMove = (e) => {
      const el = wrapRef.current;
      if (!el) return;
      const r = el.getBoundingClientRect();
      const cx = r.left + r.width / 2;
      const cy = r.top + r.height * 0.42; // head sits high in the frame
      const dx = (e.clientX - cx) / r.width;   // ~ -0.5..0.5
      const dy = (e.clientY - cy) / r.height;
      // clamp & scale — eyes are pills, so vertical range is more generous
      const maxX = 6, maxY = 14;
      setEyeOffset({
        x: Math.max(-maxX, Math.min(maxX, dx * maxX * 2)),
        y: Math.max(-maxY, Math.min(maxY, dy * maxY * 2)),
      });
    };
    window.addEventListener("mousemove", onMove);
    return () => window.removeEventListener("mousemove", onMove);
  }, [eyeTracking]);

  // ─ Blink on trigger change + on custom event ─
  useEffect(() => {
    if (blinkTrigger === undefined) return;
    setBlink(true);
    const t = setTimeout(() => setBlink(false), 220);
    return () => clearTimeout(t);
  }, [blinkTrigger]);

  useEffect(() => {
    const el = wrapRef.current;
    if (!el) return;
    const handler = () => {
      setBlink(true);
      setTimeout(() => setBlink(false), 220);
    };
    el.addEventListener("iamai:blink", handler);
    return () => el.removeEventListener("iamai:blink", handler);
  }, []);

  // ─ Random idle blinks every 4-7s ─
  useEffect(() => {
    let alive = true;
    const loop = () => {
      if (!alive) return;
      const wait = 4000 + Math.random() * 3000;
      setTimeout(() => {
        if (!alive) return;
        setBlink(true);
        setTimeout(() => setBlink(false), 200);
        loop();
      }, wait);
    };
    loop();
    return () => { alive = false; };
  }, []);

  // ─ State-derived motion params ─
  const { floatDur, haloDur, headTiltDur, eyeBrightness } = useMemo(() => {
    switch (state) {
      case "thinking":
        return { floatDur: 5.5, haloDur: 6, headTiltDur: 3.2, eyeBrightness: "thinking" };
      case "speaking":
        return { floatDur: 2.6, haloDur: 1.4, headTiltDur: 0,  eyeBrightness: "bright"   };
      case "success":
        return { floatDur: 3.0, haloDur: 2.0, headTiltDur: 0,  eyeBrightness: "bright"   };
      case "idle":
      default:
        return { floatDur: 4.0, haloDur: 4.5, headTiltDur: 0,  eyeBrightness: "normal"   };
    }
  }, [state]);

  const uid = useMemo(() => `m${Math.random().toString(36).slice(2, 8)}`, []);

  // For "thinking", we offset eye opacity in alternation with a sine animation.
  // For "speaking", brighter overall, faster halo.
  // For "success", we trigger a quick squash on mount-of-state.
  const [successPulse, setSuccessPulse] = useState(0);
  useEffect(() => {
    if (state === "success") {
      setSuccessPulse((v) => v + 1);
      // also fire a blink for the cute "✓" feel
      setBlink(true);
      setTimeout(() => setBlink(false), 240);
    }
  }, [state]);

  // Eye scaleY: 1 normally, ~0.05 during blink, 0.6 during success squash flash.
  // We animate scaleY via attribute since transform-box isn't reliable cross-browser.
  // We do this with a CSS transition on a wrapping <g> per eye.

  return (
    <div
      ref={wrapRef}
      className={`iamai-mascot ${className}`}
      style={{ width: size, height: size, display: "inline-block", ...style }}
      data-state={state}
      aria-label="IAMAI agent mascot"
      role="img"
    >
      <svg
        viewBox="0 0 1000 1000"
        xmlns="http://www.w3.org/2000/svg"
        style={{ display: "block", width: "100%", height: "100%" }}
      >
        <defs>
          {/* Head fill */}
          <linearGradient id={`${uid}-headFill`} x1="50%" y1="0%" x2="50%" y2="100%">
            <stop offset="0%"   stopColor="#1c294f" />
            <stop offset="40%"  stopColor="#0e1838" />
            <stop offset="100%" stopColor="#05091c" />
          </linearGradient>
          <linearGradient id={`${uid}-headSheen`} x1="50%" y1="0%" x2="50%" y2="100%">
            <stop offset="0%"   stopColor="rgba(200,220,255,0.55)" />
            <stop offset="35%"  stopColor="rgba(200,220,255,0.0)" />
          </linearGradient>
          <radialGradient id={`${uid}-headInner`} cx="50%" cy="100%" r="80%">
            <stop offset="0%"  stopColor="rgba(0,0,0,0.45)" />
            <stop offset="60%" stopColor="rgba(0,0,0,0.0)" />
          </radialGradient>
          {/* Eye gradient */}
          <linearGradient id={`${uid}-eyeGrad`} x1="50%" y1="0%" x2="50%" y2="100%">
            <stop offset="0%"   stopColor="#e5eeff" />
            <stop offset="30%"  stopColor="#b8cffb" />
            <stop offset="70%"  stopColor="#7aa2e0" />
            <stop offset="100%" stopColor="#4d76b8" />
          </linearGradient>
          <linearGradient id={`${uid}-eyeSheen`} x1="50%" y1="0%" x2="50%" y2="100%">
            <stop offset="0%"   stopColor="rgba(255,255,255,0.6)" />
            <stop offset="40%"  stopColor="rgba(255,255,255,0.0)" />
          </linearGradient>
          <filter id={`${uid}-eyeGlow`} x="-100%" y="-100%" width="300%" height="300%">
            <feGaussianBlur stdDeviation="10" result="b1" />
            <feGaussianBlur stdDeviation="22" in="SourceGraphic" result="b2" />
            <feMerge>
              <feMergeNode in="b2" />
              <feMergeNode in="b1" />
            </feMerge>
          </filter>
          {/* halo */}
          <radialGradient id={`${uid}-halo`} cx="50%" cy="50%" r="50%">
            <stop offset="0%"   stopColor="rgba(140,180,255,0.55)" />
            <stop offset="55%"  stopColor="rgba(140,180,255,0.18)" />
            <stop offset="100%" stopColor="rgba(140,180,255,0)" />
          </radialGradient>
        </defs>

        {showBg && <StudioBg tone={tone} />}

        {/* halo */}
        <circle cx="500" cy="500" r="340" fill={`url(#${uid}-halo)`}>
          <animate
            attributeName="r"
            values={state === "speaking" ? "330;370;330" : "320;355;320"}
            dur={`${haloDur}s`}
            repeatCount="indefinite"
          />
          <animate
            attributeName="opacity"
            values={state === "speaking" ? "0.9;1;0.9" : "0.8;1;0.8"}
            dur={`${haloDur}s`}
            repeatCount="indefinite"
          />
        </circle>

        {/* floor shadow */}
        <ellipse cx="500" cy="850" rx="200" ry="22" fill="rgba(15,25,55,1)" opacity="0.22"
                 style={{ filter: "blur(14px)" }}>
          <animate attributeName="rx" values="200;185;200" dur={`${floatDur}s`} repeatCount="indefinite" />
          <animate attributeName="opacity" values="0.22;0.16;0.22" dur={`${floatDur}s`} repeatCount="indefinite" />
        </ellipse>

        {/* HEAD — gentle floating group */}
        <g>
          <animateTransform
            attributeName="transform"
            type="translate"
            values="0 0; 0 -16; 0 0"
            dur={`${floatDur}s`}
            repeatCount="indefinite"
          />

          {/* Optional thinking head-tilt: slow rocking */}
          <g style={{ transformOrigin: "500px 500px" }}>
            {headTiltDur > 0 && (
              <animateTransform
                attributeName="transform"
                type="rotate"
                values="-3 500 500; 3 500 500; -3 500 500"
                dur={`${headTiltDur}s`}
                repeatCount="indefinite"
              />
            )}

            {/* Squircle head — drawn at center (500,500) with internal 400×400 size */}
            <g transform="translate(300 300)">
              {/* head fill */}
              <path
                d="M 130 60 C 90 60, 60 90, 60 130 L 60 270 C 60 310, 90 340, 130 340 L 270 340 C 310 340, 340 310, 340 270 L 340 130 C 340 90, 310 60, 270 60 Z"
                transform="scale(1.15) translate(-30 -30)"
                fill={`url(#${uid}-headFill)`}
              />
              <path
                d="M 130 60 C 90 60, 60 90, 60 130 L 60 270 C 60 310, 90 340, 130 340 L 270 340 C 310 340, 340 310, 340 270 L 340 130 C 340 90, 310 60, 270 60 Z"
                transform="scale(1.15) translate(-30 -30)"
                fill={`url(#${uid}-headInner)`}
              />
              <path
                d="M 130 60 C 90 60, 60 90, 60 130 L 60 175 L 340 175 L 340 130 C 340 90, 310 60, 270 60 Z"
                transform="scale(1.15) translate(-30 -30)"
                fill={`url(#${uid}-headSheen)`}
                opacity="0.7"
              />
              <ellipse cx="200" cy="69" rx="92" ry="11"
                       transform="scale(1.15) translate(-30 -30)"
                       fill="rgba(255,255,255,0.18)" />

              {/* EYE GLOW HALOS */}
              <g filter={`url(#${uid}-eyeGlow)`}
                 opacity={eyeBrightness === "bright" ? 0.75 : eyeBrightness === "thinking" ? 0.45 : 0.55}>
                <rect x="133" y="108" width="44" height="184" rx="22" fill="#82b0ff" />
                <rect x="223" y="108" width="44" height="184" rx="22" fill="#82b0ff" />
              </g>

              {/* LEFT eye */}
              <g
                ref={leftEyeRef}
                style={{
                  transform: `translate(${eyeOffset.x}px, ${eyeOffset.y}px) scaleY(${blink ? 0.06 : 1})`,
                  transformOrigin: "155px 200px",
                  transition: "transform 0.18s cubic-bezier(0.4,0,0.6,1)",
                }}
              >
                {state === "thinking" && (
                  <animate
                    attributeName="opacity"
                    values="1;0.5;1"
                    dur="1.4s"
                    begin="0s"
                    repeatCount="indefinite"
                  />
                )}
                <rect x="133" y="108" width="44" height="184" rx="22" fill={`url(#${uid}-eyeGrad)`} />
                <rect x="138" y="115" width="34" height="92" rx="17" fill={`url(#${uid}-eyeSheen)`} />
              </g>

              {/* RIGHT eye */}
              <g
                ref={rightEyeRef}
                style={{
                  transform: `translate(${eyeOffset.x}px, ${eyeOffset.y}px) scaleY(${blink ? 0.06 : 1})`,
                  transformOrigin: "245px 200px",
                  transition: "transform 0.18s cubic-bezier(0.4,0,0.6,1)",
                }}
              >
                {state === "thinking" && (
                  <animate
                    attributeName="opacity"
                    values="0.5;1;0.5"
                    dur="1.4s"
                    begin="0s"
                    repeatCount="indefinite"
                  />
                )}
                <rect x="223" y="108" width="44" height="184" rx="22" fill={`url(#${uid}-eyeGrad)`} />
                <rect x="228" y="115" width="34" height="92" rx="17" fill={`url(#${uid}-eyeSheen)`} />
              </g>
            </g>
          </g>
        </g>

        {/* SUCCESS pulse: a quick expanding ring */}
        {successPulse > 0 && (
          <circle key={successPulse} cx="500" cy="500" r="200"
                  fill="none" stroke="#82b0ff" strokeWidth="6" opacity="0.7">
            <animate attributeName="r" from="200" to="420" dur="0.8s" fill="freeze" />
            <animate attributeName="opacity" from="0.7" to="0" dur="0.8s" fill="freeze" />
            <animate attributeName="stroke-width" from="6" to="0" dur="0.8s" fill="freeze" />
          </circle>
        )}
      </svg>
    </div>
  );
}

Object.assign(window, { IamaiMascot });
