"use client"

import { useMemo, useState } from "react"
import { useRouter } from "next/navigation"
import { useQueryClient } from "@tanstack/react-query"
import { toast } from "sonner"
import { useDriveList, useDriveMutations } from "@/lib/api/hooks/use-drive-queries"
import { uploadFile } from "@/lib/api/upload"
import { nextUntitledName } from "@/lib/drive/drive-default-name"
import { apiClient, ApiRequestError } from "@/lib/api/client"
import type { DriveFileInfo } from "@/lib/api/types"
import { buildDriveDrawEditHref, buildDriveEditHref } from "@/lib/drive/drive-url"

export type DriveNewKind = "document" | "spreadsheet" | "presentation" | "drawing" | "folder"

export const DRIVE_NEW_KIND_META: Record<
  DriveNewKind,
  { ext: string; typeLabel: string; menuLabel: string }
> = {
  document: { ext: ".docx", typeLabel: "Document", menuLabel: "Document" },
  spreadsheet: { ext: ".xlsx", typeLabel: "Tableur", menuLabel: "Tableur" },
  presentation: { ext: ".pptx", typeLabel: "Présentation", menuLabel: "Présentation" },
  drawing: { ext: ".excalidraw", typeLabel: "Dessin", menuLabel: "Dessin" },
  folder: { ext: "", typeLabel: "Dossier", menuLabel: "Dossier" },
}

export const DRIVE_NEW_MENU_ITEM_CLASS =
  "gap-3 rounded-md py-2.5 pr-3 pl-3 text-[15px] focus:bg-accent/80 [&_svg]:size-5"

async function importFolderTree(
  files: FileList,
  parentPath: string,
  createFolder: ReturnType<typeof useDriveMutations>["createFolder"]
) {
  const base = parentPath === "/" ? "" : parentPath
  const created = new Set<string>()

  const ensureDir = async (dirPath: string) => {
    if (created.has(dirPath)) return
    try {
      await createFolder.mutateAsync(dirPath)
    } catch {
      /* dossier peut déjà exister */
    }
    created.add(dirPath)
  }

  for (const file of Array.from(files)) {
    const rel = file.webkitRelativePath
    if (!rel) continue
    const segments = rel.split("/")
    const name = segments.pop()
    if (!name) continue
    let dirAcc = base
    for (const segment of segments) {
      dirAcc = `${dirAcc}/${segment}`
      await ensureDir(dirAcc)
    }
    await uploadFile(`${dirAcc}/${name}`, file)
  }
}

export function useDriveNewMenu(parentPath: string) {
  const router = useRouter()
  const queryClient = useQueryClient()
  const { createFolder, createFile } = useDriveMutations()
  const base = parentPath === "/" ? "" : parentPath
  const list = useDriveList(parentPath)
  const siblingNames = useMemo(
    () => (list.data?.files ?? []).map((f) => f.name),
    [list.data?.files]
  )

  const [pendingKind, setPendingKind] = useState<DriveNewKind | null>(null)

  const refresh = () => queryClient.invalidateQueries({ queryKey: ["drive"] })

  const pendingMeta = pendingKind ? DRIVE_NEW_KIND_META[pendingKind] : null
  const defaultName =
    pendingMeta && pendingKind
      ? nextUntitledName(siblingNames, pendingMeta.typeLabel, pendingMeta.ext)
      : ""

  const confirmNew = async (rawName: string) => {
    if (!pendingKind || !pendingMeta) return
    const name = rawName.trim().replace(/\//g, "")
    if (!name) return

    if (pendingKind === "folder") {
      try {
        await createFolder.mutateAsync(`${base}/${name}`)
        toast.success("Dossier créé")
        await refresh()
      } catch {
        toast.error("Impossible de créer le dossier")
        throw new Error("folder create failed")
      }
      return
    }

    const fileName = name.endsWith(pendingMeta.ext) ? name : name + pendingMeta.ext
    try {
      const result = await createFile.mutateAsync({
        parent_path: parentPath,
        name: fileName,
        kind: pendingKind,
      })
      toast.success("Fichier créé")
      if (pendingKind === "drawing") {
        let fileId = result.file_id
        if (!fileId) {
          const info = await apiClient.get<DriveFileInfo>(
            `/drive/files/info${result.path.startsWith("/") ? result.path : `/${result.path}`}`
          )
          fileId = info.file_id
        }
        if (fileId) {
          router.push(buildDriveDrawEditHref(fileId))
        } else {
          throw new Error("file id missing")
        }
        return
      }
      const returnTo =
        typeof window !== "undefined"
          ? window.location.pathname + window.location.search
          : undefined
      router.push(buildDriveEditHref(result.path, returnTo))
    } catch (error) {
      const detail =
        error instanceof ApiRequestError
          ? error.message
          : error instanceof Error
            ? error.message
            : null
      toast.error(detail ? `Impossible de créer le fichier : ${detail}` : "Impossible de créer le fichier")
      throw new Error("file create failed")
    }
  }

  const uploadFiles = async (files: FileList | null) => {
    if (!files?.length) return
    for (const file of Array.from(files)) {
      try {
        await uploadFile(`${base}/${file.name}`, file)
      } catch {
        toast.error(`Échec : ${file.name}`)
      }
    }
    await refresh()
    toast.success("Import terminé")
  }

  const importFolder = async (files: FileList | null) => {
    if (!files?.length) return
    try {
      await importFolderTree(files, parentPath, createFolder)
      await refresh()
      toast.success("Dossier importé")
    } catch {
      toast.error("Impossible d'importer le dossier")
    }
  }

  const pickKind = (kind: DriveNewKind) => setPendingKind(kind)
  const closeNameDialog = () => setPendingKind(null)

  return {
    pendingKind,
    pendingMeta,
    defaultName,
    confirmNew,
    uploadFiles,
    importFolder,
    pickKind,
    closeNameDialog,
  }
}
