import { useCallback, useEffect, useRef } from "react";
import type { AppStore } from "@editor/store";
import { createProjectLifecycle } from "@operations/project/lifecycle";
import { projectFileName } from "@operations/project/format";
import { browserRecoveryStorage, downloadProjectFile, readProjectFile } from "@platform/browser/projectFiles";

export function useProjectLifecycle(store: AppStore) {
  const inputRef = useRef<HTMLInputElement | null>(null);
  const lifecycleRef = useRef<ReturnType<typeof createProjectLifecycle> | null>(null);

  useEffect(() => {
    const lifecycle = createProjectLifecycle({ store, storage: browserRecoveryStorage });
    lifecycleRef.current = lifecycle;
    void lifecycle.recover();
    return () => {
      lifecycle.dispose();
      lifecycleRef.current = null;
    };
  }, [store]);

  const save = useCallback(() => {
    const lifecycle = lifecycleRef.current;
    if (!lifecycle) return;
    const document = store.getState().document;
    downloadProjectFile(lifecycle.snapshot(), projectFileName(document.name));
    void lifecycle.markSaved();
  }, [store]);

  const openFilePicker = useCallback(() => inputRef.current?.click(), []);

  const openFile = useCallback(async (file: File) => {
    const lifecycle = lifecycleRef.current;
    if (!lifecycle) return;
    try {
      await lifecycle.open(await readProjectFile(file));
    } catch (error) {
      window.alert(error instanceof Error ? error.message : "The project could not be opened.");
    }
  }, []);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.defaultPrevented || (!event.metaKey && !event.ctrlKey)) return;
      if (event.key.toLowerCase() === "s") {
        event.preventDefault();
        save();
      } else if (event.shiftKey && event.key.toLowerCase() === "o") {
        event.preventDefault();
        openFilePicker();
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [openFilePicker, save]);

  const input = (
    <input
      ref={inputRef}
      type="file"
      accept=".json,.image-studio.json,application/json"
      className="hidden"
      onChange={(event) => {
        const file = event.currentTarget.files?.[0];
        event.currentTarget.value = "";
        if (file) void openFile(file);
      }}
    />
  );

  return { input, save, openFilePicker };
}
