'use client'

import type * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
import type { TTableElement } from '@udecode/plate-table'

import { PopoverAnchor } from '@radix-ui/react-popover'
import { cn, withRef } from '@udecode/cn'
import { isSelectionExpanded } from '@udecode/plate-common'
import {
  useEditorRef,
  useEditorSelector,
  useElement,
  useRemoveNodeButton,
  withHOC,
} from '@udecode/plate-common/react'
import {
  TableProvider,
  mergeTableCells,
  unmergeTableCells,
  useTableBordersDropdownMenuContentState,
  useTableElement,
  useTableElementState,
  useTableMergeState,
} from '@udecode/plate-table/react'
import type { LucideProps } from 'lucide-react'
import LazyIcon from 'src/components/atoms/LazyIcon'
import { useReadOnly, useSelected } from 'slate-react'

import { Button } from './button'
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuPortal,
  DropdownMenuTrigger,
} from './dropdown-menu'
import { PlateElement } from './plate-element'
import { Popover, PopoverContent, popoverVariants } from './popover'

export const TableBordersDropdownMenuContent = withRef<typeof DropdownMenuPrimitive.Content>(
  (props, ref) => {
    const {
      getOnSelectTableBorder,
      hasBottomBorder,
      hasLeftBorder,
      hasNoBorders,
      hasOuterBorders,
      hasRightBorder,
      hasTopBorder,
    } = useTableBordersDropdownMenuContentState()

    return (
      <DropdownMenuContent
        ref={ref}
        className={cn('min-w-[220px]')}
        align="start"
        side="right"
        sideOffset={0}
        {...props}
      >
        <DropdownMenuGroup>
          <DropdownMenuCheckboxItem
            checked={hasBottomBorder}
            onCheckedChange={getOnSelectTableBorder('bottom')}
          >
            <BorderBottom />
            <div>Bottom Border</div>
          </DropdownMenuCheckboxItem>
          <DropdownMenuCheckboxItem
            checked={hasTopBorder}
            onCheckedChange={getOnSelectTableBorder('top')}
          >
            <BorderTop />
            <div>Top Border</div>
          </DropdownMenuCheckboxItem>
          <DropdownMenuCheckboxItem
            checked={hasLeftBorder}
            onCheckedChange={getOnSelectTableBorder('left')}
          >
            <BorderLeft />
            <div>Left Border</div>
          </DropdownMenuCheckboxItem>
          <DropdownMenuCheckboxItem
            checked={hasRightBorder}
            onCheckedChange={getOnSelectTableBorder('right')}
          >
            <BorderRight />
            <div>Right Border</div>
          </DropdownMenuCheckboxItem>
        </DropdownMenuGroup>

        <DropdownMenuGroup>
          <DropdownMenuCheckboxItem
            checked={hasNoBorders}
            onCheckedChange={getOnSelectTableBorder('none')}
          >
            <BorderNone />
            <div>No Border</div>
          </DropdownMenuCheckboxItem>
          <DropdownMenuCheckboxItem
            checked={hasOuterBorders}
            onCheckedChange={getOnSelectTableBorder('outer')}
          >
            <BorderAll />
            <div>Outside Borders</div>
          </DropdownMenuCheckboxItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    )
  },
)

export const TableFloatingToolbar = withRef<typeof PopoverContent>(
  ({ children, ...props }, ref) => {
    const element = useElement<TTableElement>()
    const { props: buttonProps } = useRemoveNodeButton({ element })

    const selectionCollapsed = useEditorSelector((editor) => !isSelectionExpanded(editor), [])

    const readOnly = useReadOnly()
    const selected = useSelected()
    const editor = useEditorRef()

    const collapsed = !readOnly && selected && selectionCollapsed
    const open = !readOnly && selected

    const { canMerge, canUnmerge } = useTableMergeState()

    const mergeContent = canMerge && (
      <Button
        variant="ghost"
        onClick={() => mergeTableCells(editor)}
        contentEditable={false}
        isMenu
      >
        <LazyIcon name="combine" />
        Merge
      </Button>
    )

    const unmergeButton = canUnmerge && (
      <Button
        variant="ghost"
        onClick={() => unmergeTableCells(editor)}
        contentEditable={false}
        isMenu
      >
        <LazyIcon name="ungroup" />
        Unmerge
      </Button>
    )

    const bordersContent = collapsed && (
      <>
        <DropdownMenu modal={false}>
          <DropdownMenuTrigger asChild>
            <Button variant="ghost" isMenu>
              <BorderAll />
              Borders
            </Button>
          </DropdownMenuTrigger>

          <DropdownMenuPortal>
            <TableBordersDropdownMenuContent />
          </DropdownMenuPortal>
        </DropdownMenu>

        <Button variant="ghost" contentEditable={false} isMenu {...buttonProps}>
          <LazyIcon name="trash-2" />
          Delete
        </Button>
      </>
    )

    return (
      <Popover open={open} modal={false}>
        <PopoverAnchor asChild>{children}</PopoverAnchor>
        {(canMerge || canUnmerge || collapsed) && (
          <PopoverContent
            ref={ref}
            className={cn(popoverVariants(), 'flex w-[220px] flex-col p-1')}
            onOpenAutoFocus={(e) => e.preventDefault()}
            {...props}
          >
            {unmergeButton}
            {mergeContent}
            {bordersContent}
          </PopoverContent>
        )}
      </Popover>
    )
  },
)

export const TableElement = withHOC(
  TableProvider,
  withRef<typeof PlateElement>(({ children, className, ...props }, ref) => {
    const { colSizes, isSelectingCell, marginLeft, minColumnWidth } = useTableElementState()
    const { colGroupProps, props: tableProps } = useTableElement()

    return (
      <TableFloatingToolbar>
        <PlateElement
          className={cn('overflow-x-auto', className)}
          style={{ paddingLeft: marginLeft }}
          {...props}
        >
          <table
            ref={ref}
            className={cn(
              'my-4 ml-px mr-0 table h-px w-[calc(100%-6px)] table-fixed border-collapse',
              isSelectingCell && '[&_*::selection]:bg-none',
            )}
            {...tableProps}
          >
            <colgroup {...colGroupProps}>
              {colSizes.map((width, index) => (
                <col
                  key={index}
                  style={{
                    minWidth: minColumnWidth,
                    width: width || undefined,
                  }}
                />
              ))}
            </colgroup>

            <tbody className="min-w-full">{children}</tbody>
          </table>
        </PlateElement>
      </TableFloatingToolbar>
    )
  }),
)

const BorderAll = (props: LucideProps) => (
  <svg
    fill="currentColor"
    focusable="false"
    height="48"
    role="img"
    viewBox="0 0 24 24"
    width="48"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    <path d="M3 6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6zm10 13h5a1 1 0 0 0 1-1v-5h-6v6zm-2-6H5v5a1 1 0 0 0 1 1h5v-6zm2-2h6V6a1 1 0 0 0-1-1h-5v6zm-2-6H6a1 1 0 0 0-1 1v5h6V5z" />
  </svg>
)

const BorderBottom = (props: LucideProps) => (
  <svg
    fill="currentColor"
    focusable="false"
    height="48"
    role="img"
    viewBox="0 0 24 24"
    width="48"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    <path d="M13 5a1 1 0 1 0 0-2h-2a1 1 0 1 0 0 2h2zm-8 6a1 1 0 1 0-2 0v2a1 1 0 1 0 2 0v-2zm-2 7a1 1 0 1 1 2 0 1 1 0 0 0 1 1h12a1 1 0 0 0 1-1 1 1 0 1 1 2 0 3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm17-8a1 1 0 0 0-1 1v2a1 1 0 1 0 2 0v-2a1 1 0 0 0-1-1zM7 4a1 1 0 0 0-1-1 3 3 0 0 0-3 3 1 1 0 0 0 2 0 1 1 0 0 1 1-1 1 1 0 0 0 1-1zm11-1a1 1 0 1 0 0 2 1 1 0 0 1 1 1 1 1 0 1 0 2 0 3 3 0 0 0-3-3z" />
  </svg>
)

const BorderLeft = (props: LucideProps) => (
  <svg
    fill="currentColor"
    focusable="false"
    height="48"
    role="img"
    viewBox="0 0 24 24"
    width="48"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    <path d="M6 21a1 1 0 1 0 0-2 1 1 0 0 1-1-1V6a1 1 0 0 1 1-1 1 1 0 0 0 0-2 3 3 0 0 0-3 3v12a3 3 0 0 0 3 3zm7-16a1 1 0 1 0 0-2h-2a1 1 0 1 0 0 2h2zm6 6a1 1 0 1 1 2 0v2a1 1 0 1 1-2 0v-2zm-5 9a1 1 0 0 1-1 1h-2a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1zm4-17a1 1 0 1 0 0 2 1 1 0 0 1 1 1 1 1 0 1 0 2 0 3 3 0 0 0-3-3zm-1 17a1 1 0 0 0 1 1 3 3 0 0 0 3-3 1 1 0 1 0-2 0 1 1 0 0 1-1 1 1 1 0 0 0-1 1z" />
  </svg>
)

const BorderNone = (props: LucideProps) => (
  <svg
    fill="currentColor"
    focusable="false"
    height="48"
    role="img"
    viewBox="0 0 24 24"
    width="48"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    <path d="M14 4a1 1 0 0 1-1 1h-2a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1zm-9 7a1 1 0 1 0-2 0v2a1 1 0 1 0 2 0v-2zm14 0a1 1 0 1 1 2 0v2a1 1 0 1 1-2 0v-2zm-6 10a1 1 0 1 0 0-2h-2a1 1 0 1 0 0 2h2zM7 4a1 1 0 0 0-1-1 3 3 0 0 0-3 3 1 1 0 0 0 2 0 1 1 0 0 1 1-1 1 1 0 0 0 1-1zm11-1a1 1 0 1 0 0 2 1 1 0 0 1 1 1 1 1 0 1 0 2 0 3 3 0 0 0-3-3zM7 20a1 1 0 0 1-1 1 3 3 0 0 1-3-3 1 1 0 1 1 2 0 1 1 0 0 0 1 1 1 1 0 0 1 1 1zm11 1a1 1 0 1 1 0-2 1 1 0 0 0 1-1 1 1 0 1 1 2 0 3 3 0 0 1-3 3z" />
  </svg>
)

const BorderRight = (props: LucideProps) => (
  <svg
    fill="currentColor"
    focusable="false"
    height="48"
    role="img"
    viewBox="0 0 24 24"
    width="48"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    <path d="M13 5a1 1 0 1 0 0-2h-2a1 1 0 1 0 0 2h2zm-8 6a1 1 0 1 0-2 0v2a1 1 0 1 0 2 0v-2zm9 9a1 1 0 0 1-1 1h-2a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1zM6 3a1 1 0 0 1 0 2 1 1 0 0 0-1 1 1 1 0 0 1-2 0 3 3 0 0 1 3-3zm1 17a1 1 0 0 1-1 1 3 3 0 0 1-3-3 1 1 0 1 1 2 0 1 1 0 0 0 1 1 1 1 0 0 1 1 1zm11 1a1 1 0 1 1 0-2 1 1 0 0 0 1-1V6a1 1 0 0 0-1-1 1 1 0 1 1 0-2 3 3 0 0 1 3 3v12a3 3 0 0 1-3 3z" />
  </svg>
)

const BorderTop = (props: LucideProps) => (
  <svg
    fill="currentColor"
    focusable="false"
    height="48"
    role="img"
    viewBox="0 0 24 24"
    width="48"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    <path d="M3 6a1 1 0 0 0 2 0 1 1 0 0 1 1-1h12a1 1 0 0 1 1 1 1 1 0 1 0 2 0 3 3 0 0 0-3-3H6a3 3 0 0 0-3 3zm2 5a1 1 0 1 0-2 0v2a1 1 0 1 0 2 0v-2zm14 0a1 1 0 1 1 2 0v2a1 1 0 1 1-2 0v-2zm-5 9a1 1 0 0 1-1 1h-2a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1zm-8 1a1 1 0 1 0 0-2 1 1 0 0 1-1-1 1 1 0 1 0-2 0 3 3 0 0 0 3 3zm11-1a1 1 0 0 0 1 1 3 3 0 0 0 3-3 1 1 0 1 0-2 0 1 1 0 0 1-1 1 1 1 0 0 0-1 1z" />
  </svg>
)
