"use client"

import { useRef, useState } from "react"
import type { Editor } from "@tiptap/react"
import { Icon } from "@iconify/react"
import { ImageIcon, Pencil, Sparkles } from "lucide-react"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Button } from "@/components/ui/button"
import { DocsDriveImagePickerDialog } from "@/components/drive/richtext/docs-drive-image-picker-dialog"
import { openDocsGraphicDrawModal } from "@/components/drive/richtext/docs-graphic-draw-modal"
import {
  buildImageInsertGraphicAttrs,
  buildInsertGraphicAttrs,
} from "@/lib/drive/extensions/docs-graphic"
import {
  DOCS_GRAPHIC_PLACEMENT_LABELS,
  DOCS_GRAPHIC_WRAP_LABELS,
  type DocsGraphicFloatSide,
  type DocsGraphicPlacement,
  type DocsGraphicWrap,
  parseGraphicAttrs,
} from "@/lib/drive/docs-graphic-types"
import { suitePublicAsset } from "@/lib/suite/suite-public-asset"

function readSelectedGraphicAttrs(editor: Editor) {
  if (editor.isActive("docsGraphic")) {
    return parseGraphicAttrs(editor.getAttributes("docsGraphic") as Record<string, unknown>)
  }
  if (editor.isActive("docsInlineGraphic")) {
    return parseGraphicAttrs(editor.getAttributes("docsInlineGraphic") as Record<string, unknown>)
  }
  return null
}

export function DocsGraphicInsertMenu({
  editor,
  disabled,
}: {
  editor: Editor | null
  disabled?: boolean
}) {
  const imageInputRef = useRef<HTMLInputElement>(null)
  const [drivePickerOpen, setDrivePickerOpen] = useState(false)

  if (!editor) return null

  const insertImageSrc = (
    src: string,
    options?: { wrap?: DocsGraphicWrap; placement?: DocsGraphicPlacement; alt?: string }
  ) => {
    void buildImageInsertGraphicAttrs({
      src,
      alt: options?.alt ?? "",
      wrap: options?.wrap ?? "square",
      placement: options?.placement ?? "block",
    }).then((attrs) => {
      editor.chain().focus().insertDocsGraphic(attrs).run()
    })
  }

  const insertImageFile = (
    file: File,
    options?: { wrap?: DocsGraphicWrap; placement?: DocsGraphicPlacement }
  ) => {
    const reader = new FileReader()
    reader.onload = () => {
      const src = reader.result as string
      insertImageSrc(src, options)
    }
    reader.readAsDataURL(file)
  }

  return (
    <>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button
            type="button"
            variant="ghost"
            size="icon"
            className="docs-toolbar-btn size-7 shrink-0"
            disabled={disabled}
            aria-label="Insérer un élément graphique"
          >
            <Icon icon="material-symbols:image-outline" className="size-4" />
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="start" className="min-w-64">
          <DropdownMenuItem onClick={() => setDrivePickerOpen(true)}>
            <img
              src={suitePublicAsset("/ultidrive-mark.svg")}
              alt=""
              className="size-4 shrink-0"
              aria-hidden
            />
            Image depuis Drive
          </DropdownMenuItem>
          <DropdownMenuItem onClick={() => imageInputRef.current?.click()}>
            <ImageIcon className="size-4 shrink-0" />
            Image depuis l&apos;ordinateur
          </DropdownMenuItem>
          <DropdownMenuItem
            onClick={() => {
              editor
                .chain()
                .focus()
                .insertDocsGraphic(
                  buildInsertGraphicAttrs("draw", { width: 320, height: 240 })
                )
                .run()
              openDocsGraphicDrawModal()
            }}
          >
            <Pencil className="size-4 shrink-0" />
            Dessin
          </DropdownMenuItem>
          <DropdownMenuItem
            onClick={() =>
              editor
                .chain()
                .focus()
                .insertDocsGraphic(buildInsertGraphicAttrs("gradient"))
                .run()
            }
          >
            <Sparkles className="size-4 shrink-0" />
            Dégradé
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>

      <DocsDriveImagePickerDialog
        open={drivePickerOpen}
        onOpenChange={setDrivePickerOpen}
        onPickImage={(src, file) => {
          insertImageSrc(src, { alt: file.name })
        }}
      />

      <input
        ref={imageInputRef}
        type="file"
        accept="image/*"
        className="hidden"
        onChange={(event) => {
          const file = event.target.files?.[0]
          if (file) insertImageFile(file)
          event.target.value = ""
        }}
      />
    </>
  )
}

export function DocsGraphicLayoutMenu({
  editor,
  disabled,
}: {
  editor: Editor | null
  disabled?: boolean
}) {
  if (!editor) return null
  const attrs = readSelectedGraphicAttrs(editor)
  if (!attrs) return null

  const applyWrap = (wrap: DocsGraphicWrap) => {
    editor.chain().setDocsGraphicWrap(wrap).run()
  }
  const applyPlacement = (placement: DocsGraphicPlacement) => {
    editor.chain().focus().setDocsGraphicPlacement(placement).run()
  }
  const applyFloatSide = (floatSide: DocsGraphicFloatSide) => {
    editor.chain().focus().setDocsGraphicFloatSide(floatSide).run()
  }

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button
          type="button"
          variant="ghost"
          size="icon"
          className="docs-toolbar-btn docs-toolbar-btn--active size-7 shrink-0"
          disabled={disabled}
          aria-label="Disposition de l'élément graphique"
        >
          <Icon icon="material-symbols:layers-outline" className="size-4" />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent
        align="start"
        className="min-w-64"
        onCloseAutoFocus={(event) => event.preventDefault()}
      >
        <DropdownMenuSub>
          <DropdownMenuSubTrigger>Habillage texte</DropdownMenuSubTrigger>
          <DropdownMenuSubContent onCloseAutoFocus={(event) => event.preventDefault()}>
            {(Object.keys(DOCS_GRAPHIC_WRAP_LABELS) as DocsGraphicWrap[]).map((wrap) => (
              <DropdownMenuItem key={wrap} onClick={() => applyWrap(wrap)}>
                {DOCS_GRAPHIC_WRAP_LABELS[wrap]}
                {attrs.wrap === wrap ? " ✓" : ""}
              </DropdownMenuItem>
            ))}
          </DropdownMenuSubContent>
        </DropdownMenuSub>
        <DropdownMenuSeparator />
        <DropdownMenuSub>
          <DropdownMenuSubTrigger>Placement</DropdownMenuSubTrigger>
          <DropdownMenuSubContent>
            {(Object.keys(DOCS_GRAPHIC_PLACEMENT_LABELS) as DocsGraphicPlacement[]).map(
              (placement) => (
                <DropdownMenuItem key={placement} onClick={() => applyPlacement(placement)}>
                  {DOCS_GRAPHIC_PLACEMENT_LABELS[placement]}
                  {attrs.placement === placement ? " ✓" : ""}
                </DropdownMenuItem>
              )
            )}
          </DropdownMenuSubContent>
        </DropdownMenuSub>
        <DropdownMenuSeparator />
        <DropdownMenuSub>
          <DropdownMenuSubTrigger>Côté du flottement</DropdownMenuSubTrigger>
          <DropdownMenuSubContent>
            {(["left", "right", "center"] as const).map((side) => (
              <DropdownMenuItem key={side} onClick={() => applyFloatSide(side)}>
                {side === "left" ? "Gauche" : side === "right" ? "Droite" : "Centre"}
                {attrs.floatSide === side ? " ✓" : ""}
              </DropdownMenuItem>
            ))}
          </DropdownMenuSubContent>
        </DropdownMenuSub>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

export function readGraphicToolbarActive(editor: Editor | null): boolean {
  if (!editor) return false
  return editor.isActive("docsGraphic") || editor.isActive("docsInlineGraphic")
}
