import React, { useCallback } from 'react'
import { Node, mergeAttributes as mergeNodeAttributes } from '@tiptap/core'
import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'

function readImageAttrs(element) {
  const imageElements = Array.from(element.querySelectorAll?.('img') || [])
  const subtitleElement = element.querySelector?.('figcaption')

  return {
    leftSrc: imageElements[0]?.getAttribute('src') || '',
    leftAlt: imageElements[0]?.getAttribute('alt') || '',
    rightSrc: imageElements[1]?.getAttribute('src') || '',
    rightAlt: imageElements[1]?.getAttribute('alt') || '',
    subtitle: subtitleElement?.textContent?.trim() || '',
  }
}

function RichCompareNodeView({ editor, node, selected, updateAttributes, deleteNode, getPos }) {
  const selectNode = useCallback(() => {
    if (!editor || typeof getPos !== 'function') {
      return
    }

    editor.chain().focus().setNodeSelection(getPos()).run()
  }, [editor, getPos])

  return (
    <NodeViewWrapper
      as="figure"
      className={["rich-compare-node", selected ? 'is-selected' : ''].filter(Boolean).join(' ')}
      data-rich-compare="true"
      onMouseDown={(event) => {
        if (event.target instanceof HTMLElement && event.target.closest('input, textarea, button, select, label')) {
          return
        }

        selectNode()
      }}
    >
      <div className="rich-compare-node__grid">
        <div className="rich-compare-node__tile">
          <span className="rich-compare-node__badge">Left</span>
          <img
            src={node.attrs.leftSrc}
            alt={node.attrs.leftAlt || ''}
            className="rich-compare-node__img"
            loading="lazy"
            decoding="async"
          />
        </div>

        <div className="rich-compare-node__tile">
          <span className="rich-compare-node__badge">Right</span>
          <img
            src={node.attrs.rightSrc}
            alt={node.attrs.rightAlt || ''}
            className="rich-compare-node__img"
            loading="lazy"
            decoding="async"
          />
        </div>
      </div>

      {!selected && node.attrs.subtitle ? (
        <figcaption className="rich-compare-node__subtitle">{node.attrs.subtitle}</figcaption>
      ) : null}

      {selected ? (
        <div className="rich-compare-node__editor" contentEditable={false}>
          <div className="grid gap-3 md:grid-cols-2">
            <label className="grid gap-2 text-sm text-slate-300">
              <span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Left alt text</span>
              <input
                value={node.attrs.leftAlt || ''}
                onChange={(event) => updateAttributes({ leftAlt: event.target.value })}
                placeholder="Describe the left image"
                className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none"
              />
            </label>

            <label className="grid gap-2 text-sm text-slate-300">
              <span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Right alt text</span>
              <input
                value={node.attrs.rightAlt || ''}
                onChange={(event) => updateAttributes({ rightAlt: event.target.value })}
                placeholder="Describe the right image"
                className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none"
              />
            </label>
          </div>

          <label className="grid gap-2 text-sm text-slate-300">
            <span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Subtitle</span>
            <input
              value={node.attrs.subtitle || ''}
              onChange={(event) => updateAttributes({ subtitle: event.target.value })}
              placeholder="Visible caption below the comparison"
              className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none"
            />
          </label>

          <div className="flex flex-wrap gap-2">
            <button
              type="button"
              onClick={selectNode}
              className="rounded-2xl border border-white/10 bg-white/[0.04] px-4 py-3 text-sm font-semibold text-white transition hover:bg-white/[0.08]"
            >
              Keep selected
            </button>

            <button
              type="button"
              onClick={deleteNode}
              className="rounded-2xl border border-rose-300/20 bg-rose-400/10 px-4 py-3 text-sm font-semibold text-rose-100 transition hover:bg-rose-400/15"
            >
              Remove comparison
            </button>
          </div>
        </div>
      ) : null}
    </NodeViewWrapper>
  )
}

const RichCompare = Node.create({
  name: 'imageCompare',
  group: 'block',
  atom: true,

  addAttributes() {
    return {
      leftSrc: { default: '' },
      leftAlt: { default: '' },
      rightSrc: { default: '' },
      rightAlt: { default: '' },
      subtitle: { default: '' },
    }
  },

  parseHTML() {
    return [
      {
        tag: 'figure[data-rich-compare]',
        getAttrs: (element) => readImageAttrs(element),
      },
    ]
  },

  renderHTML({ node, HTMLAttributes }) {
    const {
      leftSrc: _leftSrc,
      leftAlt: _leftAlt,
      rightSrc: _rightSrc,
      rightAlt: _rightAlt,
      subtitle: _subtitle,
      ...figureHTMLAttributes
    } = HTMLAttributes

    const leftImageAttributes = {
      src: node.attrs.leftSrc,
      alt: node.attrs.leftAlt || '',
      loading: 'lazy',
      decoding: 'async',
      class: 'rich-compare-node__img',
    }

    const rightImageAttributes = {
      src: node.attrs.rightSrc,
      alt: node.attrs.rightAlt || '',
      loading: 'lazy',
      decoding: 'async',
      class: 'rich-compare-node__img',
    }

    return [
      'figure',
      mergeNodeAttributes(this.options.HTMLAttributes, figureHTMLAttributes, {
        'data-rich-compare': 'true',
      }),
      ['div', { class: 'rich-compare-node__grid' },
        ['div', { class: 'rich-compare-node__tile' }, ['img', leftImageAttributes]],
        ['div', { class: 'rich-compare-node__tile' }, ['img', rightImageAttributes]],
      ],
      ...(node.attrs.subtitle ? [['figcaption', { class: 'rich-compare-node__subtitle' }, node.attrs.subtitle]] : []),
    ]
  },

  addNodeView() {
    return ReactNodeViewRenderer(RichCompareNodeView)
  },
})

export default RichCompare