import React, { useState, useRef, useEffect } from 'react';
import { mergeAttributes, Node, NodeViewProps } from '@tiptap/core';
import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';
import { GripVertical, Trash2, ZoomIn, ZoomOut } from 'lucide-react';
import { Node as ProseMirrorNode, DOMOutputSpec } from 'prosemirror-model';
import ConfirmDeleteModal from "./ConfirmDeleteModal";

interface CustomImageAttributes {
  src: string | undefined;
  alt: string | undefined;
  title: string | undefined;
  scale: number;
  caption: string;
}

const ImageNodeView: React.FC<NodeViewProps> = ({ node, editor, getPos, selected, deleteNode }) => {
  const typedNode = node as ProseMirrorNode & { attrs: CustomImageAttributes };

  const scale = typedNode.attrs.scale || 1;
  const caption = typedNode.attrs.caption || '';
  const isEditable = editor.isEditable;

  const captionRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (captionRef.current && caption.trim() !== captionRef.current.innerText.trim()) {
      captionRef.current.innerText = caption;
    }
  }, [caption]);

  const [isConfirmModalOpen, setConfirmModalOpen] = useState(false);

  const handleZoomIn = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    editor.commands.updateAttributes('customImage', {
      scale: Math.min(scale + 0.1, 2),
    });
  };

  const handleZoomOut = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    editor.commands.updateAttributes('customImage', {
      scale: Math.max(scale - 0.1, 0.5),
    });
  };

  const handleDelete = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setConfirmModalOpen(true);
  };

  const handleCaptionBlur = (e: React.FocusEvent<HTMLDivElement>) => {
    const newCaption = e.currentTarget.innerText;
    if (newCaption !== caption) {
      editor.commands.command(({ tr, state }) => {
        const pos = getPos();
        if (pos == null) return false;

        const nodeAtPos = state.doc.nodeAt(pos);
        if (!nodeAtPos || nodeAtPos.type.name !== 'customImage') {
          return false;
        }

        tr.setNodeMarkup(pos, undefined, {
          ...node.attrs,
          caption: newCaption,
        });
        editor.view.dispatch(tr);

        editor.emit('update', {
          editor,
          transaction: tr,
        });

        return true;
      });
    }
  };

  return (
      <NodeViewWrapper className="relative flex flex-col items-center my-4">
        <div className="flex w-full items-start">
          {isEditable && (
              <div
                  className="drag-handle cursor-move mr-2 text-gray-400 hover:text-gray-600"
                  data-drag-handle=""
                  title="Перетащить"
              >
                <GripVertical size={16} />
              </div>
          )}

          <div className="flex-1">
            <div className="flex flex-col items-center w-full">
              <div
                  className="relative flex flex-col items-center"
                  style={{ width: `${scale * 100}%`, transition: 'width 0.2s' }}
              >
                <img
                    src={typedNode.attrs.src}
                    alt={typedNode.attrs.alt}
                    title={typedNode.attrs.title}
                    className={`max-w-full ${selected && isEditable ? 'ring-2 ring-blue-500' : ''}`}
                    data-scale={scale}
                />

                {selected && isEditable && (
                    <div className="absolute top-2 right-2 flex items-center space-x-2 bg-white bg-opacity-80 p-1 rounded shadow z-10">
                      <button type="button" onClick={handleZoomIn} className="p-1 rounded hover:bg-gray-200" title="Увеличить">
                        <ZoomIn size={16} />
                      </button>
                      <button type="button" onClick={handleZoomOut} className="p-1 rounded hover:bg-gray-200" title="Уменьшить">
                        <ZoomOut size={16} />
                      </button>
                      <button type="button" onClick={handleDelete} className="p-1 rounded hover:bg-red-200 text-red-600" title="Удалить изображение">
                        <Trash2 size={16} />
                      </button>
                      <div className="text-xs text-gray-500 ml-2">
                        {(scale * 100).toFixed(0)}%
                      </div>
                    </div>
                )}

                <div className="relative w-full mt-2">
                  <div
                      ref={captionRef}
                      className="image-caption w-[80%] mx-auto text-base font-bold text-gray-600 italic text-center outline-none relative empty:before:content-[attr(data-placeholder)] empty:before:text-gray-400 empty:before:absolute empty:before:top-1/2 empty:before:left-0 empty:before:-translate-y-1/2 empty:before:pl-4 empty:before:text-left empty:before:pointer-events-none empty:before:select-none"
                      contentEditable={isEditable}
                      suppressContentEditableWarning
                      onBlur={handleCaptionBlur}
                      data-caption={caption}
                      data-placeholder="Введите подпись..."
                  >
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <ConfirmDeleteModal
            isOpen={isConfirmModalOpen}
            onConfirm={() => {
              deleteNode();
              setConfirmModalOpen(false);
            }}
            onCancel={() => setConfirmModalOpen(false)}
        />
      </NodeViewWrapper>
  );
};

export const CustomImage = Node.create({
  name: 'customImage',
  group: 'block',
  inline: false,
  selectable: true,
  draggable: true,
  atom: true,

  addAttributes() {
    return {
      src: { default: undefined },
      alt: { default: undefined },
      title: { default: undefined },
      scale: {
        default: 1,
        parseHTML: (element) => {
          const img = element.querySelector('img');
          return img ? Number(img.getAttribute('data-scale')) || 1 : 1;
        },
        renderHTML: (attributes) => ({
          'data-scale': Number(attributes.scale) || 1,
        }),
      },
      caption: {
        default: '',
        parseHTML: (element) => {
          const captionElement = element.querySelector('div.image-caption');
          const img = element.querySelector('img');
          return captionElement
              ? captionElement.getAttribute('data-caption') || captionElement.textContent || ''
              : img?.getAttribute('data-caption') || '';
        },
        renderHTML: (attributes) => (attributes.caption ? { 'data-caption': attributes.caption } : {}),
      },
    };
  },

  parseHTML() {
    return [
      {
        tag: 'div.image-container',
        getAttrs: (element: HTMLElement) => {
          if (!(element instanceof HTMLElement)) return null;
          const img = element.querySelector('img');
          const captionElement = element.querySelector('div.image-caption');
          if (!img) return null;
          return {
            src: img.getAttribute('src') || undefined,
            alt: img.getAttribute('alt') || undefined,
            title: img.getAttribute('title') || undefined,
            scale: Number(img.getAttribute('data-scale')) || 1,
            caption: captionElement
                ? captionElement.getAttribute('data-caption') || captionElement.textContent || ''
                : img.getAttribute('data-caption') || '',
          };
        },
      },
    ];
  },

  renderHTML({ node, HTMLAttributes }) {
    const { src, alt, title, scale, caption } = node.attrs;
    const actualScale = Number(scale) || 1;

    const imageElement: DOMOutputSpec = [
      'img',
      mergeAttributes(HTMLAttributes, {
        src,
        alt,
        title,
        'data-scale': actualScale,
        style: `width: ${actualScale * 100}%`,
      }),
    ];

    const captionElement: DOMOutputSpec = [
      'div',
      {
        class: 'image-caption w-full text-sm font-bold text-gray-600 italic text-center mt-2',
        'data-caption': caption,
        'data-placeholder': 'Введите подпись...',
      },
      caption,
    ];

    return [
      'div',
      { class: 'image-container flex flex-col items-center my-4' },
      imageElement,
      caption ? captionElement : '',
    ];
  },

  addNodeView() {
    return ReactNodeViewRenderer(ImageNodeView);
  },
});
