import { useCallback, useEffect, useRef } from "react";
import { commandIds } from "@commands/ids";
import type { AppStore } from "@editor/store";

export function useImageImport(store: AppStore) {
  const inputRef = useRef<HTMLInputElement | null>(null);

  const importFile = useCallback(
    async (file: File) => {
      if (!file.type.startsWith("image/")) return;

      const source = URL.createObjectURL(file);
      const intrinsicSize = await loadImageSize(source);
      const state = store.getState();
      const artboard = state.editor.selection.artboardId
        ? state.document.artboards.find((candidate) => candidate.id === state.editor.selection.artboardId)
        : state.document.artboards[0];

      if (!artboard) {
        URL.revokeObjectURL(source);
        return;
      }

      const assetId = crypto.randomUUID();
      const layerId = crypto.randomUUID();
      const center = state.editor.viewport.center;

      store.dispatch(commandIds.documentAddAsset, {
        asset: {
          id: assetId,
          name: file.name,
          mimeType: file.type,
          source,
          intrinsicSize,
        },
      });
      store.dispatch(commandIds.documentAddImageLayer, {
        artboardId: artboard.id,
        layer: {
          id: layerId,
          type: "image",
          name: file.name,
          visible: true,
          locked: false,
          opacity: 1,
          assetId,
          transform: {
            position: { x: center.x - intrinsicSize.w / 2, y: center.y - intrinsicSize.h / 2 },
            scale: { x: 1, y: 1 },
            rotation: 0,
          },
        },
      });
      store.dispatch(commandIds.selectionSet, { artboardId: artboard.id, layerIds: [layerId] });
    },
    [store],
  );

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

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.defaultPrevented || event.key.toLowerCase() !== "o" || (!event.metaKey && !event.ctrlKey)) return;
      event.preventDefault();
      openFilePicker();
    };

    const handlePaste = (event: ClipboardEvent) => {
      const file = [...(event.clipboardData?.files ?? [])].find((candidate) => candidate.type.startsWith("image/"));
      if (!file) return;

      event.preventDefault();
      void importFile(file);
    };

    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("paste", handlePaste);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("paste", handlePaste);
    };
  }, [importFile, openFilePicker]);

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

  return { input, openFilePicker, importFile };
}

function loadImageSize(source: string): Promise<{ w: number; h: number }> {
  return new Promise((resolve, reject) => {
    const image = new Image();
    image.onload = () => resolve({ w: image.naturalWidth, h: image.naturalHeight });
    image.onerror = () => reject(new Error("Failed to load image"));
    image.src = source;
  });
}
