"use client"

import dynamic from "next/dynamic"
import { useRouter } from "next/navigation"
import { useEffect, useMemo, useRef, useState, type ReactNode } from "react"
import {
  ChevronLeft,
  ChevronRight,
  Copy,
  Download,
  ExternalLink,
  FolderInput,
  HardDrive,
  Loader2,
  Star,
  Trash2,
  UserPlus,
  X,
} from "lucide-react"
import Link from "next/link"
import { toast } from "sonner"
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogTitle,
} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { DriveMoveDialog, type DriveFolderPickerMode } from "@/components/drive/drive-move-dialog"
import { downloadDriveFile, fetchDrivePreviewBlob } from "@/lib/api/drive-download"
import { fetchPublicShareBlob } from "@/lib/api/public-share"
import { resolveDemoDrivePreview } from "@/lib/demo/demo-drive-preview"
import { useIsDemoDrive } from "@/lib/demo/demo-drive-context"
import { downloadPublicShareFile } from "@/lib/drive/open-public-share-item"
import { useDriveMutations } from "@/lib/api/hooks/use-drive-queries"
import { ApiRequestError } from "@/lib/api/client"
import { displayFileName } from "@/lib/drive/display-file-name"
import {
  drivePreviewKind,
  isSvgFile,
  previewTargetToFileInfo,
  type DrivePreviewKind,
} from "@/lib/drive/drive-preview"
import { SvgPreviewViewer } from "@/components/drive/svg-preview-viewer"
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"
import { apiClient } from "@/lib/api/client"
import { MailDriveFolderPicker } from "@/components/mail/mail-drive-folder-picker"
import { useSaveAttachmentToDrive } from "@/lib/api/hooks/use-mail-drive-save"
import {
  mailDriveFileHref,
  mailDriveFolderHref,
  mailDriveFolderLabel,
  mailDriveSaveErrorMessage,
  mailDriveSaveSuccessMessage,
} from "@/lib/mail/mail-drive"
import { cn } from "@/lib/utils"

const TEXT_PREVIEW_MAX_BYTES = 2 * 1024 * 1024

const PdfPreviewViewer = dynamic(
  () =>
    import("@/components/drive/pdf-preview-viewer").then((m) => m.PdfPreviewViewer),
  {
    ssr: false,
    loading: () => (
      <div className="flex h-full flex-col items-center justify-center gap-2 text-zinc-400">
        <Loader2 className="h-10 w-10 animate-spin" aria-hidden />
        <span className="text-sm">Ouverture du PDF…</span>
      </div>
    ),
  },
)

const PREVIEW_ACTION_BTN =
  "cursor-pointer text-zinc-300 hover:bg-white/10 hover:text-white disabled:pointer-events-none disabled:opacity-40"

function PreviewActionButton({
  label,
  onClick,
  disabled,
  className,
  children,
}: {
  label: string
  onClick: () => void
  disabled?: boolean
  className?: string
  children: ReactNode
}) {
  return (
    <Button
      type="button"
      variant="ghost"
      size="icon"
      className={cn(PREVIEW_ACTION_BTN, className)}
      onClick={onClick}
      disabled={disabled}
      aria-label={label}
    >
      {children}
    </Button>
  )
}

function PreviewBody({
  kind,
  blobUrl,
  name,
  textContent,
  svgMarkup,
  onImageError,
}: {
  kind: DrivePreviewKind
  blobUrl: string
  name: string
  textContent?: string | null
  svgMarkup?: string | null
  onImageError?: () => void
}) {
  if (kind === "text") {
    return (
      <pre className="h-full w-full overflow-auto rounded-md bg-zinc-900 p-4 text-left font-mono text-sm leading-relaxed whitespace-pre-wrap break-words text-zinc-100">
        {textContent ?? ""}
      </pre>
    )
  }
  if (svgMarkup) {
    return <SvgPreviewViewer markup={svgMarkup} name={name} />
  }
  if (kind === "image") {
    return (
      <img
        src={blobUrl}
        alt={displayFileName(name)}
        className="max-h-full max-w-full object-contain"
        onError={onImageError}
      />
    )
  }
  if (kind === "video") {
    return (
      <video
        src={blobUrl}
        controls
        autoPlay
        className="max-h-full max-w-full rounded-md bg-black"
        playsInline
      >
        <track kind="captions" />
      </video>
    )
  }
  if (kind === "audio") {
    return (
      <audio src={blobUrl} controls autoPlay className="w-full max-w-lg">
        <track kind="captions" />
      </audio>
    )
  }
  return <PdfPreviewViewer key={blobUrl} blobUrl={blobUrl} name={name} />
}

export function FilePreviewDialog() {
  const previewFiles = useDriveUIStore((s) => s.previewFiles)
  const previewIndex = useDriveUIStore((s) => s.previewIndex)
  const previewContext = useDriveUIStore((s) => s.previewContext)
  const closePreview = useDriveUIStore((s) => s.closePreview)
  const stepPreview = useDriveUIStore((s) => s.stepPreview)
  const setSharePath = useDriveUIStore((s) => s.setSharePath)
  const updatePreviewFavorite = useDriveUIStore((s) => s.updatePreviewFavorite)
  const removePreviewFile = useDriveUIStore((s) => s.removePreviewFile)
  const mutations = useDriveMutations()
  const [folderPickerMode, setFolderPickerMode] = useState<DriveFolderPickerMode | null>(null)
  const [mailSavePickerOpen, setMailSavePickerOpen] = useState(false)

  const file = previewIndex >= 0 ? (previewFiles[previewIndex] ?? null) : null
  const fileInfo = useMemo(() => (file ? previewTargetToFileInfo(file) : null), [file])
  const allowShare = previewContext?.allowShare ?? true
  const isTrash = previewContext?.isTrash ?? false
  const publicShare = previewContext?.publicShare
  const mailSource = previewContext?.mailSource ?? false
  const mailMessageId = previewContext?.mailMessageId ?? file?.mailMessageId ?? ""
  const router = useRouter()
  const isDemoDrive = useIsDemoDrive()
  const saveToDrive = useSaveAttachmentToDrive(mailMessageId)
  const isMailAttachment = mailSource && Boolean(file?.mailAttachmentId)
  const showWriteActions = !isTrash && !publicShare && !isMailAttachment
  const mailDrivePath = isMailAttachment && file?.path.startsWith("/") ? file.path : undefined
  const [blobUrl, setBlobUrl] = useState<string | null>(null)
  const [textContent, setTextContent] = useState<string | null>(null)
  const [svgMarkup, setSvgMarkup] = useState<string | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [imgFailed, setImgFailed] = useState(false)
  const [demoPreviewAsImage, setDemoPreviewAsImage] = useState(false)
  const blobUrlRef = useRef<string | null>(null)

  const kind = file ? drivePreviewKind(file) : null
  const isSvg = file ? isSvgFile(file) : false
  const hasPrev = previewIndex > 0
  const hasNext = previewIndex >= 0 && previewIndex < previewFiles.length - 1
  const positionLabel =
    previewFiles.length > 1 ? `${previewIndex + 1} / ${previewFiles.length}` : null

  const revokeBlobUrl = () => {
    if (blobUrlRef.current) {
      URL.revokeObjectURL(blobUrlRef.current)
      blobUrlRef.current = null
    }
    setBlobUrl(null)
  }

  useEffect(() => {
    if (!file || !kind) {
      revokeBlobUrl()
      setLoading(false)
      setError(null)
      setImgFailed(false)
      setTextContent(null)
      setSvgMarkup(null)
      return
    }

    let cancelled = false

    setLoading(true)
    setError(null)
    setImgFailed(false)
    setDemoPreviewAsImage(false)
    setTextContent(null)
    setSvgMarkup(null)

    ;(async () => {
      try {
        if (isDemoDrive && !publicShare && !file.mailAttachmentId) {
          const resolved = resolveDemoDrivePreview(file, { width: 1600, height: 1200 })
          if (!resolved) {
            throw new Error("Aperçu indisponible en mode démo.")
          }
          if (cancelled) return
          if (resolved.type === "text") {
            if (blobUrlRef.current) {
              URL.revokeObjectURL(blobUrlRef.current)
              blobUrlRef.current = null
            }
            setBlobUrl(null)
            setSvgMarkup(null)
            setTextContent(resolved.content)
            return
          }
          if (resolved.type === "svg") {
            if (blobUrlRef.current) {
              URL.revokeObjectURL(blobUrlRef.current)
              blobUrlRef.current = null
            }
            setBlobUrl(null)
            setSvgMarkup(resolved.markup)
            return
          }
          setTextContent(null)
          setSvgMarkup(null)
          setBlobUrl(resolved.url)
          setDemoPreviewAsImage(true)
          return
        }

        const blob = file.mailAttachmentId
          ? await apiClient.getBlob(`/mail/attachments/${file.mailAttachmentId}`)
          : publicShare
            ? await fetchPublicShareBlob(
                publicShare.token,
                { path: file.path, name: file.name, mime_type: file.mime_type },
                publicShare.password
              )
            : await fetchDrivePreviewBlob(file)
        if (cancelled) return
        if (kind === "text") {
          if (blobUrlRef.current) {
            URL.revokeObjectURL(blobUrlRef.current)
            blobUrlRef.current = null
          }
          setBlobUrl(null)
          setSvgMarkup(null)
          if (blob.size > TEXT_PREVIEW_MAX_BYTES) {
            setError("Fichier trop volumineux pour l’aperçu texte. Téléchargez-le.")
            return
          }
          setTextContent(await blob.text())
          return
        }
        if (isSvg) {
          if (blobUrlRef.current) {
            URL.revokeObjectURL(blobUrlRef.current)
            blobUrlRef.current = null
          }
          setBlobUrl(null)
          setSvgMarkup(await blob.text())
          return
        }
        const url = URL.createObjectURL(blob)
        const previous = blobUrlRef.current
        blobUrlRef.current = url
        setBlobUrl(url)
        if (previous && previous !== url) {
          URL.revokeObjectURL(previous)
        }
      } catch (err) {
        if (!cancelled) {
          const msg =
            err instanceof ApiRequestError
              ? err.message
              : "Impossible de charger l’aperçu."
          setError(msg)
        }
      } finally {
        if (!cancelled) setLoading(false)
      }
    })()

    return () => {
      cancelled = true
    }
  }, [
    file?.path,
    file?.mime_type,
    file?.mailAttachmentId,
    kind,
    isSvg,
    publicShare?.token,
    publicShare?.password,
    isDemoDrive,
  ])

  const previewReady =
    kind === "text"
      ? textContent !== null
      : isSvg
        ? svgMarkup !== null
        : Boolean(blobUrl)

  useEffect(() => {
    if (previewFiles.length === 0) return

    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === "ArrowLeft") {
        e.preventDefault()
        stepPreview(-1)
      } else if (e.key === "ArrowRight") {
        e.preventDefault()
        stepPreview(1)
      }
    }

    window.addEventListener("keydown", onKeyDown)
    return () => window.removeEventListener("keydown", onKeyDown)
  }, [previewFiles.length, stepPreview])

  useEffect(() => {
    return () => revokeBlobUrl()
  }, [])

  const title = file ? displayFileName(file.name) : ""
  const open = Boolean(file && kind)

  const onShare = () => {
    if (!file) return
    setSharePath(file.path, "file")
  }

  const onToggleFavorite = async () => {
    if (!file) return
    const next = !file.is_favorite
    try {
      await mutations.favorite.mutateAsync({ path: file.path, favorite: next })
      updatePreviewFavorite(file.path, next)
      toast.success(next ? "Ajouté aux favoris" : "Retiré des favoris")
    } catch {
      toast.error("Impossible de modifier les favoris")
    }
  }

  const onDelete = async () => {
    if (!file) return
    try {
      await mutations.deleteFile.mutateAsync(file.path)
      removePreviewFile(file.path)
      toast.success("Supprimé")
    } catch {
      toast.error("Impossible de supprimer")
    }
  }

  const favoriteLabel = file?.is_favorite ? "Retirer des favoris" : "Ajouter aux favoris"

  const onMailDownload = () => {
    if (!file?.mailAttachmentId) return
    void apiClient.getBlob(`/mail/attachments/${file.mailAttachmentId}`).then((blob) => {
      const url = URL.createObjectURL(blob)
      const a = document.createElement("a")
      a.href = url
      a.download = displayFileName(file.name)
      a.click()
      URL.revokeObjectURL(url)
    })
  }

  const onMailSaveToDrive = async (folderPath: string) => {
    if (!file?.mailAttachmentId || !mailMessageId) return
    try {
      const drivePath = await saveToDrive.mutateAsync({
        attachmentId: file.mailAttachmentId,
        folderPath,
      })
      useDriveUIStore.setState((state) => ({
        previewFiles: state.previewFiles.map((f) =>
          f.mailAttachmentId === file.mailAttachmentId
            ? { ...f, path: drivePath }
            : f
        ),
      }))
      setMailSavePickerOpen(false)
      toast.success(mailDriveSaveSuccessMessage(folderPath), {
        action: {
          label: "Ouvrir le dossier",
          onClick: () => router.push(mailDriveFolderHref(folderPath)),
        },
      })
    } catch (err) {
      toast.error(mailDriveSaveErrorMessage(err))
    }
  }

  return (
    <>
      <MailDriveFolderPicker
        open={mailSavePickerOpen}
        onOpenChange={setMailSavePickerOpen}
        title="Enregistrer dans UltiDrive"
        description="Choisissez un dossier dans votre Drive."
        confirmLabel="Enregistrer ici"
        pending={saveToDrive.isPending}
        onConfirm={onMailSaveToDrive}
      />
      <DriveMoveDialog
        open={folderPickerMode !== null}
        onOpenChange={(nextOpen) => {
          if (!nextOpen) setFolderPickerMode(null)
        }}
        mode={folderPickerMode ?? "move"}
        sources={fileInfo ? [fileInfo] : []}
        onMoved={() => {
          if (folderPickerMode === "move" && file) removePreviewFile(file.path)
          setFolderPickerMode(null)
        }}
      />
      <Dialog
        open={open}
        onOpenChange={(nextOpen) => {
          if (!nextOpen) closePreview()
        }}
      >
      <DialogContent
        aria-describedby={undefined}
        showCloseButton={false}
        overlayClassName="bg-black/90"
        className={cn(
          "flex h-[min(92dvh,920px)] w-[min(96vw,1280px)] max-w-none flex-col gap-0 overflow-hidden",
          "border-0 bg-zinc-950 p-0 text-zinc-100 shadow-2xl sm:max-w-none"
        )}
      >
        <div className="flex h-14 shrink-0 items-center gap-2 border-b border-white/10 px-4">
          <DialogTitle className="min-w-0 flex-1 truncate text-left text-base font-medium text-zinc-100">
            {title}
          </DialogTitle>
          {positionLabel ? (
            <span className="shrink-0 text-sm tabular-nums text-zinc-400">{positionLabel}</span>
          ) : null}
          {file ? (
            <div className="flex shrink-0 items-center gap-0.5">
              {showWriteActions && allowShare ? (
                <PreviewActionButton label="Partager" onClick={onShare}>
                  <UserPlus className="h-5 w-5" />
                </PreviewActionButton>
              ) : null}
              {showWriteActions ? (
                <PreviewActionButton
                  label={favoriteLabel}
                  onClick={() => void onToggleFavorite()}
                  disabled={mutations.favorite.isPending}
                  className={cn(
                    file.is_favorite && "text-amber-400 hover:bg-amber-400/10 hover:text-amber-300"
                  )}
                >
                  <Star
                    className="h-5 w-5"
                    fill={file.is_favorite ? "currentColor" : "none"}
                  />
                </PreviewActionButton>
              ) : null}
              {showWriteActions ? (
                <>
                  <PreviewActionButton
                    label="Déplacer vers"
                    onClick={() => setFolderPickerMode("move")}
                  >
                    <FolderInput className="h-5 w-5" />
                  </PreviewActionButton>
                  <PreviewActionButton
                    label="Copier vers"
                    onClick={() => setFolderPickerMode("copy")}
                    className="max-sm:hidden"
                  >
                    <Copy className="h-5 w-5" />
                  </PreviewActionButton>
                </>
              ) : null}
              {isMailAttachment && !mailDrivePath ? (
                <PreviewActionButton
                  label="Enregistrer dans UltiDrive"
                  onClick={() => setMailSavePickerOpen(true)}
                  disabled={saveToDrive.isPending}
                >
                  <HardDrive className="h-5 w-5" />
                </PreviewActionButton>
              ) : null}
              {isMailAttachment && mailDrivePath ? (
                <PreviewActionButton
                  label={`Emplacement : ${mailDriveFolderLabel(mailDrivePath)}`}
                  onClick={() => {}}
                  disabled
                  className="!w-auto max-w-[min(40vw,16rem)] px-2 opacity-100"
                >
                  <Link
                    href={mailDriveFileHref(mailDrivePath)}
                    className="inline-flex min-w-0 items-center gap-1.5 text-zinc-300 hover:text-white"
                    onClick={(e) => e.stopPropagation()}
                  >
                    <ExternalLink className="h-4 w-4 shrink-0" />
                    <span className="truncate text-xs font-normal">
                      {mailDriveFolderLabel(mailDrivePath)}
                    </span>
                  </Link>
                </PreviewActionButton>
              ) : null}
              <PreviewActionButton
                label="Télécharger"
                onClick={() =>
                  void (isMailAttachment
                    ? onMailDownload()
                    : publicShare
                      ? downloadPublicShareFile(
                          publicShare.token,
                          { path: file.path, name: file.name, mime_type: file.mime_type, type: "file", size: 0, last_modified: "", is_favorite: false, is_shared: false },
                          publicShare.password
                        )
                      : downloadDriveFile(file.path, file.name, file.name))
                }
              >
                <Download className="h-5 w-5" />
              </PreviewActionButton>
              {showWriteActions ? (
                <PreviewActionButton
                  label="Supprimer"
                  onClick={() => void onDelete()}
                  disabled={mutations.deleteFile.isPending}
                  className="hover:bg-red-500/10 hover:text-red-400"
                >
                  <Trash2 className="h-5 w-5" />
                </PreviewActionButton>
              ) : null}
              <DialogClose asChild>
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  className={PREVIEW_ACTION_BTN}
                  aria-label="Fermer"
                >
                  <X className="h-5 w-5" />
                </Button>
              </DialogClose>
            </div>
          ) : null}
        </div>

        <div className="relative flex min-h-0 flex-1 overflow-hidden">
          {hasPrev ? (
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="absolute left-2 top-1/2 z-10 h-10 w-10 -translate-y-1/2 cursor-pointer rounded-full bg-black/40 text-white hover:bg-black/60"
              onClick={() => stepPreview(-1)}
              aria-label="Fichier précédent"
            >
              <ChevronLeft className="h-6 w-6" />
            </Button>
          ) : null}
          {hasNext ? (
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="absolute right-2 top-1/2 z-10 h-10 w-10 -translate-y-1/2 cursor-pointer rounded-full bg-black/40 text-white hover:bg-black/60"
              onClick={() => stepPreview(1)}
              aria-label="Fichier suivant"
            >
              <ChevronRight className="h-6 w-6" />
            </Button>
          ) : null}

          <div
            className={cn(
              "flex min-h-0 flex-1 overflow-hidden",
              kind === "pdf" ? "flex-col p-0" : kind === "text" ? "flex-col p-4" : kind === "audio" ? "flex-col items-center justify-center p-8" : "items-center justify-center p-4"
            )}
          >
            {loading ? (
              <div className="flex flex-col items-center gap-2 text-zinc-400">
                <Loader2 className="h-10 w-10 animate-spin" aria-hidden />
                <span className="text-sm">Chargement…</span>
              </div>
            ) : null}
            {!loading && error ? (
              <p className="text-center text-sm text-zinc-400">{error}</p>
            ) : null}
            {!loading && !error && imgFailed ? (
              <p className="text-center text-sm text-zinc-400">
                Aperçu non pris en charge par le navigateur (ex. HEIC). Téléchargez le fichier.
              </p>
            ) : null}
            {!loading && !error && !imgFailed && kind && file && previewReady ? (
              <PreviewBody
                kind={demoPreviewAsImage ? "image" : kind}
                blobUrl={blobUrl ?? ""}
                name={file.name}
                textContent={textContent}
                svgMarkup={svgMarkup}
                onImageError={() => setImgFailed(true)}
              />
            ) : null}
          </div>
        </div>
      </DialogContent>
    </Dialog>
    </>
  )
}
