import * as React from 'react'
import type { Editor } from '@tiptap/core'
import { ColorHighlightPopover } from '@admin/components/custom/content-editor/tiptap-ui/color-highlight-popover'
import { HeadingDropdownMenu } from '@admin/components/custom/content-editor/tiptap-ui/heading-dropdown-menu'
import {
  LinkContent,
  LinkPopover
} from '@admin/components/custom/content-editor/tiptap-ui/link-popover'
import { ListDropdownMenu } from '@admin/components/custom/content-editor/tiptap-ui/list-dropdown-menu'
import { MarkButton } from '@admin/components/custom/content-editor/tiptap-ui/mark-button'
import { Separator } from '@admin/components/ui/separator'
import { cn } from '@admin/utils/shared/cn'
import { BubbleMenu } from '@tiptap/react/menus'

const HIDDEN_SELECTION_TOOLBAR_TYPES = [
  'mediaGalleryPlaceholder',
  'image',
  'horizontalRule',
  'codeBlock',
  'code',
  'inlineMath',
  'rawContentBlock',
  'link',
  'table',
  'tableCell',
  'tableHeader'
] as const

export function SelectionBubbleMenu({ editor }: { editor: Editor }) {
  const [hasOpenSelectionMenuChild, setHasOpenSelectionMenuChild] = React.useState(false)
  const hasOpenSelectionMenuChildRef = React.useRef(false)
  const setSelectionMenuChildOpen = React.useCallback((isOpen: boolean) => {
    hasOpenSelectionMenuChildRef.current = isOpen
    setHasOpenSelectionMenuChild(isOpen)
  }, [])
  const handleSelectionMenuChildOpenChange = React.useCallback(
    (isOpen: boolean) => {
      setSelectionMenuChildOpen(isOpen)
    },
    [setSelectionMenuChildOpen]
  )
  const handleSelectionMenuPointerDown = React.useCallback(
    (event: React.PointerEvent<HTMLDivElement>) => {
      const target = event.target
      if (!(target instanceof Element)) return

      const menuTrigger = target.closest('button[aria-haspopup], button[aria-expanded]')
      if (menuTrigger) {
        setSelectionMenuChildOpen(true)
      }
    },
    [setSelectionMenuChildOpen]
  )

  return (
    <>
      <BubbleMenu
        editor={editor}
        pluginKey="linkBubbleMenu"
        updateDelay={0}
        shouldShow={({ editor: currentEditor }) =>
          currentEditor.isEditable && currentEditor.isActive('link')
        }
        options={{
          placement: 'top',
          offset: 8,
          flip: { padding: 8 },
          shift: { padding: 8 }
        }}
      >
        <div
          role="toolbar"
          aria-label="Link formatting toolbar"
          className={cn(
            'flex items-center gap-1 overflow-x-auto rounded-sm border border-border bg-popover p-4 text-foreground shadow-2xl [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',
            'relative z-50'
          )}
        >
          <LinkContent editor={editor} />
        </div>
      </BubbleMenu>

      <BubbleMenu
        editor={editor}
        pluginKey="selectionBubbleMenu"
        updateDelay={0}
        shouldShow={({ editor: currentEditor, from, to }) =>
          currentEditor.isEditable &&
          (from !== to || hasOpenSelectionMenuChild || hasOpenSelectionMenuChildRef.current) &&
          HIDDEN_SELECTION_TOOLBAR_TYPES.every((type) => !currentEditor.isActive(type))
        }
        options={{
          placement: 'top',
          offset: 8,
          flip: { padding: 8 },
          shift: { padding: 8 }
        }}
      >
        <div
          role="toolbar"
          aria-label="Selection formatting toolbar"
          onPointerDownCapture={handleSelectionMenuPointerDown}
          className={cn(
            'flex items-center gap-1 overflow-x-auto rounded-sm border border-border bg-popover p-1 text-popover-foreground shadow-menu [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',
            'relative z-50'
          )}
        >
          <div className="flex items-center gap-0.5">
            <HeadingDropdownMenu
              editor={editor}
              onOpenChange={handleSelectionMenuChildOpenChange}
            />
            <ListDropdownMenu
              editor={editor}
              types={['bulletList', 'orderedList', 'taskList']}
              onOpenChange={handleSelectionMenuChildOpenChange}
            />
          </div>

          <Separator orientation="vertical" className="mx-1 my-auto h-[65%] self-center" />

          <div className="flex items-center gap-0.5">
            <MarkButton editor={editor} type="bold" />
            <MarkButton editor={editor} type="italic" />
            <MarkButton editor={editor} type="strike" />
            <MarkButton editor={editor} type="code" />
            <MarkButton editor={editor} type="underline" />
            <ColorHighlightPopover
              editor={editor}
              onOpenChange={handleSelectionMenuChildOpenChange}
            />
            <LinkPopover editor={editor} onOpenChange={handleSelectionMenuChildOpenChange} />
          </div>
        </div>
      </BubbleMenu>
    </>
  )
}
