import { useCallback, useEffect, useRef } from "react";
import { useEditorStore } from "@/stores/editorStore";

const DEBOUNCE_MS = 400;

/**
 * Debounced hook that compiles µFrame source via POST /api/compile.
 * Automatically triggers on ufSource changes.
 */
export function useCompile() {
  const ufSource = useEditorStore((s) => s.ufSource);
  const setCompileResult = useEditorStore((s) => s.setCompileResult);
  const setCompiling = useEditorStore((s) => s.setCompiling);
  const setCompileError = useEditorStore((s) => s.setCompileError);

  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const abortRef = useRef<AbortController | null>(null);

  const compile = useCallback(
    async (source: string) => {
      if (!source.trim()) {
        setCompileResult("", "", "", false, []);
        return;
      }

      // Abort any in-flight request
      abortRef.current?.abort();
      const controller = new AbortController();
      abortRef.current = controller;

      setCompiling(true);

      try {
        const res = await fetch("/api/compile", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ source }),
          signal: controller.signal,
        });

        if (!res.ok) {
          const err = await res.json().catch(() => ({ detail: "Compile failed" }));
          setCompileError(err.detail || "Compile failed");
          return;
        }

        const data = await res.json();
        setCompileResult(data.ascii, data.micron, data.script || "", data.is_dynamic || false, data.warnings || []);
      } catch (e: unknown) {
        if (e instanceof DOMException && e.name === "AbortError") return;
        setCompileError(e instanceof Error ? e.message : "Compile failed");
      }
    },
    [setCompileResult, setCompiling, setCompileError],
  );

  useEffect(() => {
    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => compile(ufSource), DEBOUNCE_MS);
    return () => {
      if (timerRef.current) clearTimeout(timerRef.current);
    };
  }, [ufSource, compile]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      abortRef.current?.abort();
    };
  }, []);
}
