import { useEffect, useRef, useState } from "react";
import pointerSvg from "@/assets/pointer.min.svg";

/**
 * Floating pointer that tracks the CodeMirror cursor with smooth lerp animation.
 * Positions itself right next to the left border of the editor container.
 * Uses a ResizeObserver to keep horizontal position synced on window resize.
 */
export default function EditorPointer() {
  const [y, setY] = useState<number | null>(null);
  const [editorLeft, setEditorLeft] = useState<number | null>(null);
  const targetRef = useRef(0);
  const currentRef = useRef(0);
  const rafRef = useRef(0);
  const activeRef = useRef(false);
  const [clickKey, setClickKey] = useState(0);
  const clickTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
  const cmRef = useRef<Element | null>(null);
  const [eyeOffset, setEyeOffset] = useState({ x: 0, y: 0 });
  const eyeTargetRef = useRef({ x: 0, y: 0 });
  const eyeCurrentRef = useRef({ x: 0, y: 0 });

  useEffect(() => {
    const ease = 0.09;
    const eyeEase = 0.06;

    const updateLeft = () => {
      if (cmRef.current) {
        setEditorLeft(cmRef.current.getBoundingClientRect().left);
      }
    };

    const onMouseMove = (e: MouseEvent) => {
      const pointerX = (cmRef.current?.getBoundingClientRect().left ?? 0) - 100;
      const pointerY = currentRef.current;
      const dx = e.clientX - pointerX;
      const dy = e.clientY - pointerY;
      const dist = Math.sqrt(dx * dx + dy * dy) || 1;
      const maxShift = 1.5;
      eyeTargetRef.current = {
        x: (dx / dist) * maxShift,
        y: (dy / dist) * maxShift,
      };
    };

    window.addEventListener("mousemove", onMouseMove);

    const onEditorClick = () => {
      clearTimeout(clickTimerRef.current);
      setClickKey((k) => k + 1);
      clickTimerRef.current = setTimeout(() => setClickKey(0), 200);
    };

    const onCursorMove = (e: Event) => {
      const { top } = (e as CustomEvent).detail;
      targetRef.current = top;

      // Find editor container and attach click listener lazily
      if (!cmRef.current) {
        const cm = document.querySelector(".cm-editor");
        if (cm) {
          cmRef.current = cm;
          cm.addEventListener("mousedown", onEditorClick);
          ro.observe(cm);
        }
      }
      updateLeft();

      if (!activeRef.current) {
        currentRef.current = top;
        setY(top);
        activeRef.current = true;
      }
    };

    const tick = () => {
      if (activeRef.current) {
        const diff = targetRef.current - currentRef.current;
        if (Math.abs(diff) < 0.5) {
          currentRef.current = targetRef.current;
        } else {
          currentRef.current += diff * ease;
        }
        setY(currentRef.current);
      }
      // Lerp eyes toward target
      const ec = eyeCurrentRef.current;
      const et = eyeTargetRef.current;
      ec.x += (et.x - ec.x) * eyeEase;
      ec.y += (et.y - ec.y) * eyeEase;
      setEyeOffset({ x: ec.x, y: ec.y });
      rafRef.current = requestAnimationFrame(tick);
    };

    window.addEventListener("cm-cursor-move", onCursorMove);
    rafRef.current = requestAnimationFrame(tick);

    // Keep left position updated on resize
    const ro = new ResizeObserver(() => updateLeft());
    const existingCm = document.querySelector(".cm-editor");
    if (existingCm) {
      cmRef.current = existingCm;
      ro.observe(existingCm);
    }
    window.addEventListener("resize", updateLeft);

    return () => {
      window.removeEventListener("cm-cursor-move", onCursorMove);
      window.removeEventListener("mousemove", onMouseMove);
      window.removeEventListener("resize", updateLeft);
      cmRef.current?.removeEventListener("mousedown", onEditorClick);
      cancelAnimationFrame(rafRef.current);
      ro.disconnect();
    };
  }, []);

  if (y === null || editorLeft === null) return null;

  return (
    <div
      className={`editor-pointer${clickKey ? " editor-pointer-click" : ""}`}
      key={clickKey}
      style={{ top: y, left: editorLeft }}
    >
      <div
        className="editor-pointer-img"
        style={{
          WebkitMaskImage: `url(${pointerSvg})`,
          maskImage: `url(${pointerSvg})`,
        }}
      />
      <div className="editor-pointer-eye" style={{ top: 33, left: 134 }}>
        <div
          className="editor-pointer-iris"
          style={{ transform: `translate(${eyeOffset.x}px, ${eyeOffset.y}px)` }}
        />
      </div>
      <div className="editor-pointer-eye" style={{ top: 29, left: 144 }}>
        <div
          className="editor-pointer-iris"
          style={{ transform: `translate(${eyeOffset.x}px, ${eyeOffset.y}px)` }}
        />
      </div>
    </div>
  );
}
