"use client"

import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useRouter } from "next/navigation"
import Link from "next/link"
import { apiClient } from "@/lib/api/client"
import { getOnlyOfficeUrl } from "@/lib/runtime-config"
import { Button } from "@/components/ui/button"
import { ArrowLeft } from "lucide-react"
import { OnlyOfficeMount } from "@/components/drive/onlyoffice-mount"
import { OfficeEditorChrome } from "@/components/drive/office-editor-chrome"
import { useDriveMutations, useDriveShares } from "@/lib/api/hooks/use-drive-queries"
import { displayFileBaseName } from "@/lib/drive/display-file-name"
import { resolveRenameName } from "@/lib/drive/drive-default-name"
import { driveFolderHref } from "@/lib/drive/drive-sidebar-tree"
import { buildDriveEditHref, resolveDriveEditReturnTo } from "@/lib/drive/drive-url"
import { resolveOnlyOfficeEditorKind } from "@/lib/drive/onlyoffice-formats"
import { useDriveDocumentTitle } from "@/lib/drive/use-drive-document-title"
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"

function fileNameFromPath(filePath: string): string {
  return filePath.split("/").filter(Boolean).pop() ?? filePath
}

function renameTargetPath(filePath: string, newName: string): string {
  const parent = filePath.replace(/\/[^/]+$/, "") || "/"
  const base = parent === "/" ? "" : parent
  return `${base}/${newName}`.replace(/\/+/g, "/") || `/${newName}`
}

export function OfficeEditor({
  filePath,
  returnTo,
}: {
  filePath: string
  returnTo?: string | null
}) {
  const router = useRouter()
  const instanceSeq = useRef(0)
  const setSharePath = useDriveUIStore((s) => s.setSharePath)
  const [config, setConfig] = useState<Record<string, unknown> | null>(null)
  const [serverUrl, setServerUrl] = useState("")
  const [editorId, setEditorId] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [displayPath, setDisplayPath] = useState(filePath)

  useEffect(() => {
    setDisplayPath(filePath)
  }, [filePath])

  const fileName = fileNameFromPath(displayPath)
  const title = displayFileBaseName(fileName)
  const editorKind = resolveOnlyOfficeEditorKind({ name: fileName })
  useDriveDocumentTitle(title, editorKind)

  const backHref = useMemo(
    () =>
      resolveDriveEditReturnTo(returnTo, displayPath, (folderPath) =>
        driveFolderHref("files", folderPath)
      ),
    [returnTo, displayPath]
  )

  const { data: sharesData } = useDriveShares(displayPath, Boolean(displayPath))
  const { rename } = useDriveMutations()

  const handleEditorError = useCallback((message: string) => {
    setError(message)
  }, [])

  useEffect(() => {
    let cancelled = false
    setConfig(null)
    setServerUrl("")
    setEditorId(null)
    setError(null)

    void (async () => {
      try {
        const res = await apiClient.post<{
          config: Record<string, unknown>
          serverUrl: string
        }>("/office/session", { path: displayPath, mode: "edit" })
        if (cancelled) return
        instanceSeq.current += 1
        setConfig(res.config)
        setServerUrl(res.serverUrl || getOnlyOfficeUrl() || "")
        setEditorId(`ultidrive-editor-${instanceSeq.current}`)
      } catch {
        if (!cancelled) setError("Impossible de charger l’éditeur.")
      }
    })()

    return () => {
      cancelled = true
    }
  }, [displayPath])

  const handleRename = useCallback(
    async (input: string) => {
      const newName = resolveRenameName(
        { name: fileName, type: "file" },
        input
      )
      if (displayFileBaseName(fileName) === input.trim()) return
      await rename.mutateAsync({ path: displayPath, new_name: newName })
      const nextPath = renameTargetPath(displayPath, newName)
      setDisplayPath(nextPath)
      router.replace(buildDriveEditHref(nextPath, returnTo ?? undefined))
    },
    [displayPath, fileName, rename, returnTo, router]
  )

  const openShareDialog = useCallback(() => {
    setSharePath(displayPath, "file")
  }, [displayPath, setSharePath])

  if (error) {
    return (
      <div className="flex h-dvh flex-col items-center justify-center gap-4">
        <p className="text-destructive">{error}</p>
        <Button asChild variant="outline">
          <Link href={backHref}>
            <ArrowLeft className="mr-2 h-4 w-4" />
            Retour
          </Link>
        </Button>
      </div>
    )
  }

  if (!config || !editorId || !serverUrl) {
    return <p className="p-8 text-center text-muted-foreground">Ouverture du document…</p>
  }

  const docServer = serverUrl.replace(/\/$/, "")

  return (
    <div className="flex h-dvh flex-col">
      <OfficeEditorChrome
        backHref={backHref}
        backLabel="Drive"
        title={title}
        onRename={handleRename}
        shares={sharesData?.shares ?? []}
        onShareClick={openShareDialog}
        showShare
        showAccount
      />
      <div className="relative min-h-0 flex-1">
        <OnlyOfficeMount
          editorId={editorId}
          documentServerUrl={docServer}
          config={config}
          onError={handleEditorError}
        />
      </div>
    </div>
  )
}
