"use client"

import { memo, useCallback, useEffect, useState } from "react"
import { createPortal } from "react-dom"
import type { Editor } from "@tiptap/react"
import { Icon } from "@iconify/react"
import {
  ArrowDownToLine,
  ArrowUpToLine,
  Columns2,
  Merge,
  PaintBucket,
  Rows2,
  Split,
  Square,
  Trash2,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  docsClearTableCellBorders,
  docsDefaultTableBorder,
  docsSetTableCellBackground,
  docsSetTableCellBordersAll,
  docsSetTableCellVerticalAlign,
  docsTableActive,
  docsTableCanMerge,
  docsTableCanSplit,
} from "@/lib/drive/docs-table-actions"
import {
  DOCS_TABLE_BORDER_COLOR_PRESETS,
  DOCS_TABLE_CELL_BACKGROUND_PRESETS,
} from "@/lib/drive/docs-table-types"
import { cn } from "@/lib/utils"

function ToolbarDivider() {
  return <span className="mx-0.5 h-6 w-px shrink-0 bg-border" aria-hidden />
}

function IconToolbarButton({
  label,
  disabled,
  onClick,
  children,
}: {
  label: string
  disabled?: boolean
  onClick: () => void
  children: React.ReactNode
}) {
  return (
    <Button
      type="button"
      variant="ghost"
      size="icon"
      className="size-8 shrink-0 rounded-full text-popover-foreground hover:bg-accent hover:text-accent-foreground"
      aria-label={label}
      title={label}
      disabled={disabled}
      onClick={onClick}
    >
      {children}
    </Button>
  )
}

function DocsTableFloatingToolbarInner({
  editor,
  canvasRef,
  disabled,
}: {
  editor: Editor | null
  canvasRef: React.RefObject<HTMLElement | null>
  disabled?: boolean
}) {
  const [rect, setRect] = useState<DOMRect | null>(null)
  const [, setTick] = useState(0)

  const refresh = useCallback(() => {
    setTick((value) => value + 1)
    if (!editor || !docsTableActive(editor)) {
      setRect(null)
      return
    }

    const selectedCell = editor.view.dom.querySelector(
      "td.selectedCell, th.selectedCell, .ProseMirror-selectednode table"
    ) as HTMLElement | null

    const table =
      selectedCell?.closest("table") ??
      (editor.view.dom.querySelector(".ProseMirror-selectednode table") as HTMLElement | null)

    if (!table) {
      setRect(null)
      return
    }

    setRect(table.getBoundingClientRect())
  }, [editor])

  useEffect(() => {
    if (!editor) return
    refresh()
    editor.on("selectionUpdate", refresh)
    editor.on("transaction", refresh)
    const canvas = canvasRef.current
    canvas?.addEventListener("scroll", refresh, { passive: true })
    window.addEventListener("resize", refresh)
    return () => {
      editor.off("selectionUpdate", refresh)
      editor.off("transaction", refresh)
      canvas?.removeEventListener("scroll", refresh)
      window.removeEventListener("resize", refresh)
    }
  }, [canvasRef, editor, refresh])

  if (!editor || disabled || !docsTableActive(editor) || !rect) return null

  const canMerge = docsTableCanMerge(editor)
  const canSplit = docsTableCanSplit(editor)

  const toolbar = (
    <div
      className="docs-table-floating-toolbar pointer-events-auto fixed z-200 -translate-x-1/2"
      style={{ left: rect.left + rect.width / 2, top: Math.max(8, rect.top - 44) }}
      role="toolbar"
      aria-label="Options de tableau"
    >
      <div className="flex items-center gap-0.5 rounded-full border border-border bg-popover px-1 py-0.5 text-popover-foreground shadow-md">
        <IconToolbarButton
          label="Insérer une ligne au-dessus"
          onClick={() => editor.chain().focus().addRowBefore().run()}
        >
          <ArrowUpToLine className="size-3.5" />
        </IconToolbarButton>
        <IconToolbarButton
          label="Insérer une ligne en dessous"
          onClick={() => editor.chain().focus().addRowAfter().run()}
        >
          <ArrowDownToLine className="size-3.5" />
        </IconToolbarButton>
        <ToolbarDivider />
        <IconToolbarButton
          label="Insérer une colonne à gauche"
          onClick={() => editor.chain().focus().addColumnBefore().run()}
        >
          <Columns2 className="size-3.5 -scale-x-100" />
        </IconToolbarButton>
        <IconToolbarButton
          label="Insérer une colonne à droite"
          onClick={() => editor.chain().focus().addColumnAfter().run()}
        >
          <Columns2 className="size-3.5" />
        </IconToolbarButton>
        <ToolbarDivider />
        <IconToolbarButton
          label="Fusionner les cellules"
          disabled={!canMerge}
          onClick={() => editor.chain().focus().mergeCells().run()}
        >
          <Merge className="size-3.5" />
        </IconToolbarButton>
        <IconToolbarButton
          label="Scinder la cellule"
          disabled={!canSplit}
          onClick={() => editor.chain().focus().splitCell().run()}
        >
          <Split className="size-3.5" />
        </IconToolbarButton>
        <ToolbarDivider />
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="size-8 shrink-0 rounded-full"
              aria-label="Bordures de cellule"
              title="Bordures de cellule"
            >
              <Square className="size-3.5" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="center" className="min-w-48">
            <DropdownMenuItem
              onClick={() =>
                docsSetTableCellBordersAll(editor, docsDefaultTableBorder("#000000"))
              }
            >
              Bordures noires
            </DropdownMenuItem>
            <DropdownMenuItem onClick={() => docsClearTableCellBorders(editor)}>
              Supprimer les bordures
            </DropdownMenuItem>
            <DropdownMenuSeparator />
            {DOCS_TABLE_BORDER_COLOR_PRESETS.slice(0, 6).map((color) => (
              <DropdownMenuItem
                key={color}
                onClick={() =>
                  docsSetTableCellBordersAll(editor, docsDefaultTableBorder(color))
                }
              >
                <span
                  className="mr-2 inline-block size-4 rounded-sm border border-border"
                  style={{ backgroundColor: color }}
                  aria-hidden
                />
                {color}
              </DropdownMenuItem>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="size-8 shrink-0 rounded-full"
              aria-label="Couleur de cellule"
              title="Couleur de cellule"
            >
              <PaintBucket className="size-3.5" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="center" className="min-w-44">
            {DOCS_TABLE_CELL_BACKGROUND_PRESETS.map((preset) => (
              <DropdownMenuItem
                key={preset.id || "none"}
                onClick={() => docsSetTableCellBackground(editor, preset.color || null)}
              >
                <span
                  className="mr-2 inline-block size-4 rounded-sm border border-border"
                  style={{ backgroundColor: preset.color || "transparent" }}
                  aria-hidden
                />
                {preset.label}
              </DropdownMenuItem>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="size-8 shrink-0 rounded-full"
              aria-label="Alignement vertical"
              title="Alignement vertical"
            >
              <Rows2 className="size-3.5" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="center">
            <DropdownMenuItem onClick={() => docsSetTableCellVerticalAlign(editor, "top")}>
              Haut
            </DropdownMenuItem>
            <DropdownMenuItem onClick={() => docsSetTableCellVerticalAlign(editor, "middle")}>
              Milieu
            </DropdownMenuItem>
            <DropdownMenuItem onClick={() => docsSetTableCellVerticalAlign(editor, "bottom")}>
              Bas
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className={cn("size-8 shrink-0 rounded-full")}
              aria-label="Plus d'options"
              title="Plus d'options"
            >
              <Icon icon="material-symbols:more-horiz" className="size-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="min-w-52">
            <DropdownMenuItem onClick={() => editor.chain().focus().toggleHeaderRow().run()}>
              Ligne d&apos;en-tête
            </DropdownMenuItem>
            <DropdownMenuItem onClick={() => editor.chain().focus().toggleHeaderColumn().run()}>
              Colonne d&apos;en-tête
            </DropdownMenuItem>
            <DropdownMenuSeparator />
            <DropdownMenuItem onClick={() => editor.chain().focus().deleteRow().run()}>
              Supprimer la ligne
            </DropdownMenuItem>
            <DropdownMenuItem onClick={() => editor.chain().focus().deleteColumn().run()}>
              Supprimer la colonne
            </DropdownMenuItem>
            <DropdownMenuItem
              className="text-destructive focus:text-destructive"
              onClick={() => editor.chain().focus().deleteTable().run()}
            >
              <Trash2 className="mr-2 size-4" />
              Supprimer le tableau
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    </div>
  )

  return createPortal(toolbar, document.body)
}

export const DocsTableFloatingToolbar = memo(DocsTableFloatingToolbarInner)
