"use client"

import { useCallback, useMemo, useRef, useState, type ReactNode } from "react"
import type { Editor } from "@tiptap/react"
import type { DocsInsertMenuActions } from "@/components/drive/richtext/docs-insert-menu"
import { DocsDriveDrawPickerDialog } from "@/components/drive/richtext/docs-drive-draw-picker-dialog"
import { DocsDriveImagePickerDialog } from "@/components/drive/richtext/docs-drive-image-picker-dialog"
import { DocsPageNumbersDialog } from "@/components/drive/richtext/docs-header-footer-dialogs"
import { openDocsGraphicDrawModal } from "@/lib/drive/docs-graphic-draw-bridge"
import { importExcalidrawFromDriveFile } from "@/lib/drive/docs-graphic-draw-import"
import { openDocsLinkPopover } from "@/lib/drive/docs-link-bridge"
import { startDocsRegionEdit } from "@/lib/drive/docs-page-elements-bridge"
import type { DocPageSetup } from "@/lib/drive/doc-page-setup"
import {
  buildImageInsertGraphicAttrs,
  buildInsertGraphicAttrs,
} from "@/lib/drive/extensions/docs-graphic"
import type { DriveFileInfo } from "@/lib/api/types"

export function useDocsInsertMenu({
  editor,
  disabled,
  pageSetup,
  onPageSetupPatch,
}: {
  editor: Editor | null
  disabled?: boolean
  pageSetup?: DocPageSetup | null
  onPageSetupPatch?: (patch: Partial<DocPageSetup>) => void
}) {
  const imageInputRef = useRef<HTMLInputElement>(null)
  const [driveImagePickerOpen, setDriveImagePickerOpen] = useState(false)
  const [driveDrawPickerOpen, setDriveDrawPickerOpen] = useState(false)
  const [pageNumbersOpen, setPageNumbersOpen] = useState(false)

  const insertImageSrc = useCallback(
    (src: string, options?: { alt?: string }) => {
      if (!editor) return
      void buildImageInsertGraphicAttrs({
        src,
        alt: options?.alt ?? "",
        wrap: "square",
        placement: "block",
      }).then((attrs) => {
        editor.chain().focus().insertDocsGraphic(attrs).run()
      })
    },
    [editor]
  )

  const insertImageFile = useCallback(
    (file: File) => {
      const reader = new FileReader()
      reader.onload = () => {
        const src = reader.result as string
        insertImageSrc(src, { alt: file.name })
      }
      reader.readAsDataURL(file)
    },
    [insertImageSrc]
  )

  const applyPageNumbers = useCallback(
    (placement: "header" | "footer") => {
      onPageSetupPatch?.({
        pageNumbers: {
          enabled: true,
          placement,
          align: "right",
          startAt: pageSetup?.pageNumbers?.startAt ?? 1,
          showOnFirstPage: pageSetup?.pageNumbers?.showOnFirstPage ?? true,
        },
      })
      startDocsRegionEdit(placement)
    },
    [onPageSetupPatch, pageSetup?.pageNumbers]
  )

  const actions = useMemo<DocsInsertMenuActions>(
    () => ({
      onInsertImageFromComputer: () => imageInputRef.current?.click(),
      onInsertImageFromDrive: () => setDriveImagePickerOpen(true),
      onInsertNewDraw: () => {
        if (!editor) return
        editor
          .chain()
          .focus()
          .insertDocsGraphic(
            buildInsertGraphicAttrs("draw", { width: 320, height: 240, drawDriveFileId: null })
          )
          .run()
        openDocsGraphicDrawModal()
      },
      onInsertDrawFromDrive: () => setDriveDrawPickerOpen(true),
      onInsertLink: () => openDocsLinkPopover(),
      onInsertHorizontalRule: () => {
        editor?.chain().focus().insertContent({ type: "horizontalRule" }).run()
      },
      onInsertTable: (rows, cols) => {
        editor
          ?.chain()
          .focus()
          .insertTable({ rows, cols, withHeaderRow: false })
          .run()
      },
      onInsertHeader: () => startDocsRegionEdit("header"),
      onInsertFooter: () => startDocsRegionEdit("footer"),
      onInsertWatermark: () => {
        const text = window.prompt("Texte du filigrane", pageSetup?.pageBackground?.watermark?.text ?? "")
        if (text == null || !text.trim()) return
        onPageSetupPatch?.({
          pageBackground: {
            ...pageSetup?.pageBackground,
            watermark: {
              kind: "text",
              text: text.trim(),
              color: pageSetup?.pageBackground?.watermark?.color ?? "#b4b4b4",
              opacity: pageSetup?.pageBackground?.watermark?.opacity ?? 0.35,
              rotationDeg: pageSetup?.pageBackground?.watermark?.rotationDeg ?? -35,
            },
          },
        })
      },
      onInsertPageNumbersHeader: () => applyPageNumbers("header"),
      onInsertPageNumbersFooter: () => applyPageNumbers("footer"),
      onOpenPageNumbersOptions: () => setPageNumbersOpen(true),
    }),
    [applyPageNumbers, editor, onPageSetupPatch, pageSetup?.pageBackground]
  )

  const handlePickDriveImage = useCallback(
    async (src: string, file: DriveFileInfo) => {
      insertImageSrc(src, { alt: file.name })
    },
    [insertImageSrc]
  )

  const handlePickDriveDraw = useCallback(
    async (file: DriveFileInfo) => {
      if (!editor) return
      const imported = await importExcalidrawFromDriveFile(file)
      editor
        .chain()
        .focus()
        .insertDocsGraphic(
          buildInsertGraphicAttrs("draw", {
            drawScene: imported.drawScene,
            src: imported.src,
            width: imported.width,
            height: imported.height,
            drawDriveFileId: imported.drawDriveFileId,
            alt: imported.alt,
            lockAspectRatio: true,
          })
        )
        .run()
    },
    [editor]
  )

  const dialogs: ReactNode = (
    <>
      <DocsDriveImagePickerDialog
        open={driveImagePickerOpen}
        onOpenChange={setDriveImagePickerOpen}
        onPickImage={handlePickDriveImage}
      />
      <DocsDriveDrawPickerDialog
        open={driveDrawPickerOpen}
        onOpenChange={setDriveDrawPickerOpen}
        onPickDraw={handlePickDriveDraw}
      />
      <DocsPageNumbersDialog
        open={pageNumbersOpen}
        onOpenChange={setPageNumbersOpen}
        settings={pageSetup?.pageNumbers}
        onApply={(pageNumbers) => onPageSetupPatch?.({ pageNumbers })}
      />
      <input
        ref={imageInputRef}
        type="file"
        accept="image/*"
        className="hidden"
        onChange={(event) => {
          const file = event.target.files?.[0]
          if (file) insertImageFile(file)
          event.target.value = ""
        }}
      />
    </>
  )

  return {
    actions,
    dialogs,
    disabled,
    pageElementsEnabled: Boolean(onPageSetupPatch),
  }
}
