"use client"

import { useCallback, useEffect, useRef, useState } from "react"
import type { Editor } from "@tiptap/react"
import { Link2, Loader2, Search } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import type { DriveFileInfo } from "@/lib/api/types"
import { useDriveSearchSuggestions } from "@/lib/api/hooks/use-drive-queries"
import { DriveFileTypeIcon } from "@/lib/drive/drive-file-icon"
import { itemLocationLabel } from "@/lib/drive/drive-search"
import { DOCS_LINK_POPOVER_EVENT } from "@/lib/drive/docs-link-bridge"
import { normalizeDocsLinkHref, resolveDriveItemLinkHref } from "@/lib/drive/docs-link-href"
import { displayFileName } from "@/lib/drive/display-file-name"
import { useDebouncedValue } from "@/lib/hooks/use-debounced-value"
import { cn } from "@/lib/utils"

type SavedSelection = { from: number; to: number }

function DocsLinkToolbarBtn({
  active,
  disabled,
  onPrepareOpen,
}: {
  active?: boolean
  disabled?: boolean
  onPrepareOpen: () => void
}) {
  return (
    <Button
      type="button"
      variant="ghost"
      size="icon"
      className={cn(
        "docs-toolbar-btn size-7 shrink-0",
        active && "docs-toolbar-btn--active"
      )}
      disabled={disabled}
      aria-label="Hyperlien"
      title="Hyperlien"
      aria-pressed={active}
      onMouseDown={(event) => {
        event.preventDefault()
        onPrepareOpen()
      }}
    >
      <Link2 className="size-4" />
    </Button>
  )
}

function DriveFileSuggestionRow({
  item,
  disabled,
  onPick,
}: {
  item: DriveFileInfo
  disabled?: boolean
  onPick: (item: DriveFileInfo) => void
}) {
  return (
    <button
      type="button"
      disabled={disabled}
      className="flex w-full min-w-0 items-center gap-2 rounded-md px-2 py-1.5 text-left hover:bg-accent disabled:pointer-events-none disabled:opacity-50"
      onMouseDown={(event) => event.preventDefault()}
      onClick={() => onPick(item)}
    >
      <DriveFileTypeIcon file={item} className="size-4 shrink-0" />
      <span className="min-w-0 flex-1">
        <span className="block truncate text-sm">{displayFileName(item.name)}</span>
        <span className="block truncate text-xs text-muted-foreground">
          {itemLocationLabel(item.path, item.type)}
        </span>
      </span>
    </button>
  )
}

export function DocsLinkPopover({
  editor,
  disabled,
  active,
}: {
  editor: Editor
  disabled?: boolean
  active?: boolean
}) {
  const [open, setOpen] = useState(false)
  const [linkUrl, setLinkUrl] = useState("")
  const [driveQuery, setDriveQuery] = useState("")
  const [resolvingDriveFile, setResolvingDriveFile] = useState(false)
  const urlInputRef = useRef<HTMLInputElement>(null)
  const selectionRef = useRef<SavedSelection | null>(null)
  const debouncedDriveQuery = useDebouncedValue(driveQuery, 250)

  const { data: driveResults, isFetching: driveLoading } = useDriveSearchSuggestions(
    debouncedDriveQuery,
    "all",
    "/",
    open
  )
  const driveSuggestions = driveResults?.files ?? []

  const hasTextSelection = useCallback(() => {
    const sel = selectionRef.current
    return Boolean(sel && sel.from !== sel.to)
  }, [])

  const applyLink = useCallback(
    (rawUrl?: string) => {
      const url = normalizeDocsLinkHref(rawUrl ?? linkUrl)
      const sel = selectionRef.current

      let chain = editor.chain().focus()
      if (sel && sel.from !== sel.to) {
        chain = chain.setTextSelection({ from: sel.from, to: sel.to })
      } else if (editor.isActive("link")) {
        chain = chain.extendMarkRange("link")
      } else {
        return
      }

      if (!url) {
        chain.unsetLink().run()
      } else {
        chain.setLink({ href: url }).run()
      }

      setOpen(false)
      setLinkUrl("")
      setDriveQuery("")
      selectionRef.current = null
    },
    [editor, linkUrl]
  )

  const prepareOpen = useCallback(() => {
    const { from, to } = editor.state.selection
    selectionRef.current = { from, to }
    const prev = editor.getAttributes("link").href as string | undefined
    setLinkUrl(prev ?? "")
    setDriveQuery("")
  }, [editor])

  const pickDriveFile = useCallback(
    async (file: DriveFileInfo) => {
      setResolvingDriveFile(true)
      try {
        const href = await resolveDriveItemLinkHref(file)
        setLinkUrl(href)
        applyLink(href)
      } catch {
        window.alert("Impossible de créer le lien vers ce fichier.")
      } finally {
        setResolvingDriveFile(false)
      }
    },
    [applyLink]
  )

  useEffect(() => {
    if (!open) return
    const id = window.requestAnimationFrame(() => {
      urlInputRef.current?.focus()
      urlInputRef.current?.select()
    })
    return () => window.cancelAnimationFrame(id)
  }, [open])

  useEffect(() => {
    const onOpenRequest = () => {
      prepareOpen()
      setOpen(true)
    }
    window.addEventListener(DOCS_LINK_POPOVER_EVENT, onOpenRequest)
    return () => window.removeEventListener(DOCS_LINK_POPOVER_EVENT, onOpenRequest)
  }, [prepareOpen])

  const canApply = hasTextSelection() || editor.isActive("link")
  const trimmedDriveQuery = driveQuery.trim()

  return (
    <Popover
      open={open}
      onOpenChange={(next) => {
        setOpen(next)
        if (!next) {
          setLinkUrl("")
          setDriveQuery("")
          selectionRef.current = null
        }
      }}
    >
      <PopoverTrigger asChild>
        <DocsLinkToolbarBtn
          active={active}
          disabled={disabled}
          onPrepareOpen={prepareOpen}
        />
      </PopoverTrigger>
      <PopoverContent className="w-80 p-0" align="start" sideOffset={6}>
        <div className="border-b px-3 py-2">
          <label htmlFor="docs-link-url" className="mb-1.5 block text-xs font-medium text-muted-foreground">
            Adresse du lien
          </label>
          <div className="flex gap-2">
            <input
              ref={urlInputRef}
              id="docs-link-url"
              type="text"
              inputMode="url"
              value={linkUrl}
              placeholder="https:// ou /drive/…"
              disabled={disabled || resolvingDriveFile}
              className="h-8 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring"
              onChange={(event) => setLinkUrl(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === "Enter") {
                  event.preventDefault()
                  applyLink()
                }
              }}
            />
            <Button
              type="button"
              size="sm"
              disabled={disabled || !canApply || resolvingDriveFile}
              onClick={() => applyLink()}
            >
              OK
            </Button>
          </div>
          {!canApply ? (
            <p className="mt-1.5 text-xs text-muted-foreground">
              Sélectionnez du texte pour créer un hyperlien.
            </p>
          ) : null}
        </div>

        <div className="px-3 py-2">
          <label htmlFor="docs-link-drive-search" className="mb-1.5 block text-xs font-medium text-muted-foreground">
            Fichier du Drive
          </label>
          <div className="relative">
            <Search className="pointer-events-none absolute left-2 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
            <input
              id="docs-link-drive-search"
              type="search"
              value={driveQuery}
              placeholder="Rechercher un fichier…"
              disabled={disabled || resolvingDriveFile}
              className="h-8 w-full rounded-md border border-input bg-background py-0 pl-7 pr-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring"
              onChange={(event) => setDriveQuery(event.target.value)}
            />
          </div>
        </div>

        <div className="max-h-48 overflow-y-auto border-t px-1 py-1">
          {resolvingDriveFile ? (
            <div className="flex items-center gap-2 px-2 py-3 text-sm text-muted-foreground">
              <Loader2 className="size-4 animate-spin" />
              Création du lien…
            </div>
          ) : trimmedDriveQuery.length < 2 ? (
            <p className="px-2 py-3 text-xs text-muted-foreground">
              Saisissez au moins 2 caractères pour rechercher dans votre Drive.
            </p>
          ) : driveLoading ? (
            <div className="flex items-center gap-2 px-2 py-3 text-sm text-muted-foreground">
              <Loader2 className="size-4 animate-spin" />
              Recherche…
            </div>
          ) : driveSuggestions.length === 0 ? (
            <p className="px-2 py-3 text-sm text-muted-foreground">
              Aucun fichier pour « {trimmedDriveQuery} »
            </p>
          ) : (
            driveSuggestions.map((item) => (
              <DriveFileSuggestionRow
                key={item.path}
                item={item}
                disabled={disabled || !canApply}
                onPick={pickDriveFile}
              />
            ))
          )}
        </div>

        {editor.isActive("link") ? (
          <div className="border-t px-2 py-1.5">
            <Button
              type="button"
              variant="ghost"
              size="sm"
              className="h-7 w-full justify-start text-destructive hover:text-destructive"
              disabled={disabled}
              onClick={() => applyLink("")}
            >
              Supprimer le lien
            </Button>
          </div>
        ) : null}
      </PopoverContent>
    </Popover>
  )
}
