import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner";
import { autocompletion } from "@codemirror/autocomplete";
import type { StoreApi } from "zustand";
import { useStore } from "zustand";
import * as api from "@/api/client";
import { createEditorStore, type EditorStore } from "@/stores/editorStore";
import { usePagesStore } from "@/stores/pagesStore";
import { useCompile } from "@/hooks/useCompile";
import { useUnsavedGuard } from "@/hooks/useUnsavedGuard";
import { useKeyboardSave } from "@/hooks/useKeyboardSave";
import { uframeHighlight } from "./uframeHighlight";
import { uframeCommandSource, uframeValueHintSource, loadCommandsFromApi } from "./uframeCommands";
import { keywordHoverTooltip } from "./uframeHover";
import { EditorStoreContext } from "./EditorStoreContext";
import EditorPointer from "./EditorPointer";
import PreviewPane from "./PreviewPane";
import SourcePane from "./SourcePane";
import ToolBar from "./ToolBar";
import FloatingWindow from "@/components/shared/FloatingWindow";
import type { ManagedWindow } from "@/hooks/useWindowManager";
import {
  ResizablePanelGroup,
  ResizablePanel,
  ResizableHandle,
} from "@/components/ui/resizable";

export interface EditorWinData {
  pageName: string;
  isNew: boolean;
}

interface EditorWindowProps {
  win: ManagedWindow<EditorWinData>;
  focused: boolean;
  onUpdate: (id: string, patch: Partial<ManagedWindow<EditorWinData>>) => void;
  onClose: (id: string) => void;
  onFocus: (id: string) => void;
}

export default function EditorWindow({ win, focused, onUpdate, onClose, onFocus }: EditorWindowProps) {
  const storeRef = useRef<StoreApi<EditorStore>>(null);
  if (!storeRef.current) storeRef.current = createEditorStore();
  const store = storeRef.current;
  const windowRef = useRef<HTMLDivElement>(null);

  const ufSource = useStore(store, (s) => s.ufSource);
  const isDirty = useStore(store, (s) => s.isDirty);
  const setSource = useStore(store, (s) => s.setSource);
  const setDirty = useStore(store, (s) => s.setDirty);
  const setCurrentPage = useStore(store, (s) => s.setCurrentPage);

  const { fetchPages } = usePagesStore();
  const [pageName, setPageName] = useState(win.data.pageName);
  const [saving, setSaving] = useState(false);

  const extensions = useMemo(
    () => [
      ...uframeHighlight(),
      autocompletion({
        override: [uframeCommandSource, uframeValueHintSource],
        icons: false,
        activateOnTyping: true,
      }),
      keywordHoverTooltip,
    ],
    [],
  );

  useEffect(() => { loadCommandsFromApi(); }, []);
  useCompile(store);
  useUnsavedGuard(store);

  // Load page on mount
  useEffect(() => {
    if (!win.data.isNew && win.data.pageName) {
      api.fetchPage(win.data.pageName).then((data) => {
        if (data.source != null) {
          store.setState({ ufSource: data.source, isDirty: false });
        }
      });
    }
    return () => store.getState().reset();
  }, []);

  const handleSave = useCallback(
    async (publish: boolean) => {
      const slug = pageName.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-");
      if (!slug) { toast.error("Enter a page name."); return; }
      setSaving(true);
      try {
        const meta = await api.savePage(slug, ufSource, publish);
        setCurrentPage(meta);
        setDirty(false);
        fetchPages();
        toast.success(publish ? "Published" : "Draft saved");
        if (win.data.isNew) {
          setPageName(slug);
          onUpdate(win.id, { data: { pageName: slug, isNew: false } });
        }
      } catch (e) {
        toast.error(`Save failed: ${e}`);
      } finally {
        setSaving(false);
      }
    },
    [pageName, ufSource, win.data.isNew, win.id],
  );

  useKeyboardSave(
    useCallback(() => handleSave(false), [handleSave]),
    useCallback(() => handleSave(true), [handleSave]),
    focused,
  );

  // Confirm close if dirty
  const handleClose = useCallback((id: string) => {
    if (isDirty) {
      if (!window.confirm("You have unsaved changes. Close anyway?")) return;
    }
    onClose(id);
  }, [isDirty, onClose]);

  return (
    <FloatingWindow
      id={win.id}
      title={pageName || "new page"}
      x={win.x} y={win.y} w={win.w} h={win.h}
      zIndex={win.zIndex}
      focused={focused}
      onUpdate={onUpdate}
      onClose={handleClose}
      onFocus={onFocus}
      minW={480} minH={300}
      containerRef={windowRef}
    >
      <EditorStoreContext.Provider value={store}>
        <EditorPointer containerRef={windowRef} focused={focused} />
        <div className="flex flex-col h-full">
          <ToolBar
            pageName={pageName}
            onNameChange={win.data.isNew ? setPageName : undefined}
            onSaveDraft={() => handleSave(false)}
            onPublish={() => handleSave(true)}
            saving={saving}
            isDirty={isDirty}
          />
          <ResizablePanelGroup orientation="horizontal" className="flex-1 min-h-0">
            <ResizablePanel defaultSize={50} minSize={20}>
              <SourcePane ufSource={ufSource} setSource={setSource} extensions={extensions} />
            </ResizablePanel>
            <ResizableHandle />
            <ResizablePanel defaultSize={50} minSize={20}>
              <PreviewPane />
            </ResizablePanel>
          </ResizablePanelGroup>
        </div>
      </EditorStoreContext.Provider>
    </FloatingWindow>
  );
}


