import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import * as React from 'react';
import { NodeViewWrapper } from '../../../../../../../../node_modules/.pnpm/@tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tip_b42b5b2d59902d8a01cd4cc3e2d5dc64/node_modules/@tiptap/react/dist/index.mjs';
import { useDragResize } from '../hooks/use-drag-resize.mjs';
import { ResizeHandle } from './resize-handle.mjs';
import { cn } from '../../../../../lib/utils.mjs';
import { Controlled } from '../../../../../../../../node_modules/.pnpm/react-medium-image-zoom@5.4.0_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/react-medium-image-zoom/dist/index.mjs';
import { ActionWrapper, ActionButton, ImageActions } from './image-actions.mjs';
import { useImageActions } from '../hooks/use-image-actions.mjs';
import { blobUrlToBase64, randomId } from '../../../utils.mjs';
import { InfoCircledIcon, TrashIcon } from '../../../../../../../../node_modules/.pnpm/@radix-ui_react-icons@1.3.2_react@19.2.0/node_modules/@radix-ui/react-icons/dist/react-icons.esm.mjs';
import { ImageOverlay } from './image-overlay.mjs';
import { Spinner } from '../../../components/spinner.mjs';

const MAX_HEIGHT = 600;
const MIN_HEIGHT = 120;
const MIN_WIDTH = 120;
const normalizeUploadResponse = (res) => ({
  src: typeof res === "string" ? res : res.src,
  id: typeof res === "string" ? randomId() : res.id
});
const ImageViewBlock = ({
  editor,
  node,
  selected,
  updateAttributes
}) => {
  const {
    src: initialSrc,
    width: initialWidth,
    height: initialHeight,
    fileName
  } = node.attrs;
  const uploadAttemptedRef = React.useRef(false);
  const initSrc = React.useMemo(() => {
    if (typeof initialSrc === "string") {
      return initialSrc;
    }
    return initialSrc.src;
  }, [initialSrc]);
  const [imageState, setImageState] = React.useState({
    src: initSrc,
    isServerUploading: false,
    imageLoaded: false,
    isZoomed: false,
    error: false,
    naturalSize: { width: initialWidth, height: initialHeight }
  });
  const containerRef = React.useRef(null);
  const [activeResizeHandle, setActiveResizeHandle] = React.useState(null);
  const onDimensionsChange = React.useCallback(
    ({ width, height }) => {
      updateAttributes({ width, height });
    },
    [updateAttributes]
  );
  const aspectRatio = React.useMemo(() => {
    const { width, height } = imageState.naturalSize;
    if (!height || height <= 0 || !width || width <= 0) {
      return 1;
    }
    return width / height;
  }, [imageState.naturalSize]);
  const maxWidth = MAX_HEIGHT * aspectRatio;
  const containerMaxWidth = containerRef.current ? parseFloat(
    getComputedStyle(containerRef.current).getPropertyValue(
      "--editor-width"
    )
  ) : Infinity;
  const { isLink, onView, onDownload, onCopy, onCopyLink, onRemoveImg } = useImageActions({
    editor,
    node,
    src: imageState.src,
    onViewClick: (isZoomed) => setImageState((prev) => ({ ...prev, isZoomed }))
  });
  const {
    currentWidth,
    currentHeight,
    updateDimensions,
    initiateResize,
    isResizing
  } = useDragResize({
    initialWidth: initialWidth ?? imageState.naturalSize.width,
    initialHeight: initialHeight ?? imageState.naturalSize.height,
    contentWidth: imageState.naturalSize.width,
    contentHeight: imageState.naturalSize.height,
    gridInterval: 0.1,
    onDimensionsChange,
    minWidth: MIN_WIDTH,
    minHeight: MIN_HEIGHT,
    maxWidth: containerMaxWidth > 0 ? containerMaxWidth : maxWidth
  });
  const shouldMerge = React.useMemo(() => currentWidth <= 180, [currentWidth]);
  const handleImageLoad = React.useCallback(
    (ev) => {
      const img = ev.target;
      const newNaturalSize = {
        width: img.naturalWidth,
        height: img.naturalHeight
      };
      setImageState((prev) => ({
        ...prev,
        naturalSize: newNaturalSize,
        imageLoaded: true
      }));
      updateAttributes({
        width: img.width || newNaturalSize.width,
        height: img.height || newNaturalSize.height,
        alt: img.alt,
        title: img.title
      });
      if (!initialWidth) {
        updateDimensions((state) => ({ ...state, width: newNaturalSize.width }));
      }
    },
    [initialWidth, updateAttributes, updateDimensions]
  );
  const handleImageError = React.useCallback(() => {
    setImageState((prev) => ({ ...prev, error: true, imageLoaded: true }));
  }, []);
  const handleResizeStart = React.useCallback(
    (direction) => (event) => {
      setActiveResizeHandle(direction);
      initiateResize(direction)(event);
    },
    [initiateResize]
  );
  const handleResizeEnd = React.useCallback(() => {
    setActiveResizeHandle(null);
  }, []);
  React.useEffect(() => {
    if (!isResizing) {
      handleResizeEnd();
    }
  }, [isResizing, handleResizeEnd]);
  React.useEffect(() => {
    const handleImage = async () => {
      if (!initSrc.startsWith("blob:") || uploadAttemptedRef.current) {
        return;
      }
      uploadAttemptedRef.current = true;
      const imageExtension = editor.options.extensions.find(
        (ext) => ext.name === "image"
      );
      const { uploadFn } = imageExtension?.options ?? {};
      if (!uploadFn) {
        try {
          const base64 = await blobUrlToBase64(initSrc);
          setImageState((prev) => ({ ...prev, src: base64 }));
          updateAttributes({ src: base64 });
        } catch {
          setImageState((prev) => ({ ...prev, error: true }));
        }
        return;
      }
      try {
        setImageState((prev) => ({ ...prev, isServerUploading: true }));
        const response = await fetch(initSrc);
        const blob = await response.blob();
        const file = new File([blob], fileName, { type: blob.type });
        const url = await uploadFn(file, editor);
        const normalizedData = normalizeUploadResponse(url);
        setImageState((prev) => ({
          ...prev,
          ...normalizedData,
          isServerUploading: false
        }));
        updateAttributes(normalizedData);
      } catch {
        setImageState((prev) => ({
          ...prev,
          error: true,
          isServerUploading: false
        }));
      }
    };
    handleImage();
  }, [editor, fileName, initSrc, updateAttributes]);
  return /* @__PURE__ */ jsx(
    NodeViewWrapper,
    {
      ref: containerRef,
      "data-drag-handle": true,
      className: "relative text-center leading-none",
      children: /* @__PURE__ */ jsx(
        "div",
        {
          className: "group/node-image relative mx-auto rounded-md object-contain",
          style: {
            maxWidth: `min(${maxWidth}px, 100%)`,
            width: currentWidth,
            maxHeight: MAX_HEIGHT,
            aspectRatio: `${aspectRatio}`
          },
          children: /* @__PURE__ */ jsxs(
            "div",
            {
              className: cn(
                "relative flex h-full cursor-default flex-col items-center gap-2 rounded",
                {
                  "outline-primary outline-2 outline-offset-1": selected || isResizing
                }
              ),
              children: [
                /* @__PURE__ */ jsxs("div", { className: "h-full contain-paint", children: [
                  /* @__PURE__ */ jsxs("div", { className: "relative h-full", children: [
                    imageState.isServerUploading && !imageState.error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { className: "size-7" }) }),
                    imageState.error && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: [
                      /* @__PURE__ */ jsx(InfoCircledIcon, { className: "text-destructive size-8" }),
                      /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-2 text-sm", children: "Failed to load image" })
                    ] }),
                    /* @__PURE__ */ jsx(
                      Controlled,
                      {
                        isZoomed: imageState.isZoomed,
                        onZoomChange: () => setImageState((prev) => ({ ...prev, isZoomed: false })),
                        children: /* @__PURE__ */ jsx(
                          "img",
                          {
                            className: cn(
                              "h-auto rounded object-contain transition-shadow",
                              {
                                "opacity-0": !imageState.imageLoaded || imageState.error
                              }
                            ),
                            style: {
                              maxWidth: `min(100%, ${maxWidth}px)`,
                              minWidth: `${MIN_WIDTH}px`,
                              maxHeight: MAX_HEIGHT
                            },
                            width: currentWidth,
                            height: currentHeight,
                            src: imageState.src,
                            onError: handleImageError,
                            onLoad: handleImageLoad,
                            alt: node.attrs.alt || "",
                            title: node.attrs.title || "",
                            id: node.attrs.id
                          }
                        )
                      }
                    )
                  ] }),
                  imageState.isServerUploading && /* @__PURE__ */ jsx(ImageOverlay, {}),
                  editor.isEditable && imageState.imageLoaded && !imageState.error && !imageState.isServerUploading && /* @__PURE__ */ jsxs(Fragment, { children: [
                    /* @__PURE__ */ jsx(
                      ResizeHandle,
                      {
                        onPointerDown: handleResizeStart("left"),
                        className: cn("left-1", {
                          hidden: isResizing && activeResizeHandle === "right"
                        }),
                        isResizing: isResizing && activeResizeHandle === "left"
                      }
                    ),
                    /* @__PURE__ */ jsx(
                      ResizeHandle,
                      {
                        onPointerDown: handleResizeStart("right"),
                        className: cn("right-1", {
                          hidden: isResizing && activeResizeHandle === "left"
                        }),
                        isResizing: isResizing && activeResizeHandle === "right"
                      }
                    )
                  ] })
                ] }),
                imageState.error && /* @__PURE__ */ jsx(ActionWrapper, { children: /* @__PURE__ */ jsx(
                  ActionButton,
                  {
                    icon: /* @__PURE__ */ jsx(TrashIcon, {}),
                    tooltip: "Remove image",
                    onClick: onRemoveImg
                  }
                ) }),
                !isResizing && !imageState.error && !imageState.isServerUploading && /* @__PURE__ */ jsx(
                  ImageActions,
                  {
                    shouldMerge,
                    isLink,
                    onView,
                    onDownload,
                    onCopy,
                    onCopyLink
                  }
                )
              ]
            }
          )
        }
      )
    }
  );
};

export { ImageViewBlock };
