"use client"

import { useState, useEffect, useCallback, useRef } from "react"
import { useTranslations } from "next-intl"
import {
  ChevronRight,
  ChevronUp,
  FolderIcon,
  FolderOpenIcon,
  Home,
  Loader2,
} from "lucide-react"
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { ScrollArea } from "@/components/ui/scroll-area"
import { cn } from "@/lib/utils"
import { getHomeDirectory, listDirectoryEntries } from "@/lib/api"
import type { DirectoryEntry } from "@/lib/types"

interface DirectoryBrowserDialogProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  onSelect: (path: string) => void
  title?: string
  initialPath?: string
}

export function DirectoryBrowserDialog({
  open,
  onOpenChange,
  onSelect,
  title,
  initialPath,
}: DirectoryBrowserDialogProps) {
  const t = useTranslations("DirectoryBrowser")

  const [rootPath, setRootPath] = useState("")
  const [pathInput, setPathInput] = useState("")
  const [entries, setEntries] = useState<Map<string, DirectoryEntry[]>>(
    new Map()
  )
  const [expandedPaths, setExpandedPaths] = useState<Set<string>>(new Set())
  const [selectedPath, setSelectedPath] = useState<string | null>(null)
  const [loading, setLoading] = useState<Set<string>>(new Set())
  const [error, setError] = useState<string | null>(null)

  const initialized = useRef(false)

  const loadEntries = useCallback(
    async (path: string): Promise<DirectoryEntry[] | null> => {
      // Already cached
      if (entries.has(path)) return entries.get(path)!

      setLoading((prev) => new Set(prev).add(path))
      setError(null)
      try {
        const result = await listDirectoryEntries(path)
        setEntries((prev) => new Map(prev).set(path, result))
        return result
      } catch {
        setError(t("errorLoadingDir"))
        return null
      } finally {
        setLoading((prev) => {
          const next = new Set(prev)
          next.delete(path)
          return next
        })
      }
    },
    [entries, t]
  )

  const navigateTo = useCallback(
    async (path: string) => {
      const result = await loadEntries(path)
      if (result !== null) {
        setRootPath(path)
        setPathInput(path)
        setExpandedPaths(new Set())
        setSelectedPath(null)
      }
    },
    [loadEntries]
  )

  // Initialize on open
  useEffect(() => {
    if (!open) {
      initialized.current = false
      return
    }
    if (initialized.current) return
    initialized.current = true

    const init = async () => {
      try {
        const startPath = initialPath || (await getHomeDirectory())
        setRootPath(startPath)
        setPathInput(startPath)
        setSelectedPath(null)
        setExpandedPaths(new Set())
        setEntries(new Map())
        setError(null)
        setLoading(new Set([startPath]))

        const result = await listDirectoryEntries(startPath)
        setEntries(new Map([[startPath, result]]))
        setLoading(new Set())
      } catch {
        setError(t("errorLoadingDir"))
        setLoading(new Set())
      }
    }
    init()
  }, [open, initialPath, t])

  const handleToggleExpand = useCallback(
    async (path: string) => {
      const newExpanded = new Set(expandedPaths)
      if (newExpanded.has(path)) {
        newExpanded.delete(path)
        setExpandedPaths(newExpanded)
      } else {
        await loadEntries(path)
        newExpanded.add(path)
        setExpandedPaths(newExpanded)
      }
    },
    [expandedPaths, loadEntries]
  )

  const handleSelect = useCallback(
    (path: string) => {
      setSelectedPath(path === selectedPath ? null : path)
    },
    [selectedPath]
  )

  const handleConfirm = useCallback(() => {
    if (selectedPath) {
      onSelect(selectedPath)
      onOpenChange(false)
    }
  }, [selectedPath, onSelect, onOpenChange])

  const handleNavigateUp = useCallback(() => {
    if (!rootPath) return
    const parts = rootPath.replace(/\/$/, "").split("/")
    if (parts.length <= 1) return
    parts.pop()
    const parent = parts.join("/") || "/"
    navigateTo(parent)
  }, [rootPath, navigateTo])

  const handleGoHome = useCallback(async () => {
    try {
      const home = await getHomeDirectory()
      navigateTo(home)
    } catch {
      setError(t("errorLoadingDir"))
    }
  }, [navigateTo, t])

  const handlePathInputKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === "Enter" && pathInput.trim()) {
        navigateTo(pathInput.trim())
      }
    },
    [pathInput, navigateTo]
  )

  const handleDoubleClick = useCallback(
    (path: string) => {
      onSelect(path)
      onOpenChange(false)
    },
    [onSelect, onOpenChange]
  )

  const renderEntries = (parentPath: string, depth: number) => {
    const children = entries.get(parentPath)
    const isLoading = loading.has(parentPath)

    if (isLoading) {
      return (
        <div
          className="flex items-center gap-2 py-2 text-sm text-muted-foreground"
          style={{ paddingLeft: `${depth * 20 + 8}px` }}
        >
          <Loader2 className="size-3.5 animate-spin" />
          <span>{t("loading")}</span>
        </div>
      )
    }

    if (!children) return null

    if (children.length === 0) {
      return (
        <div
          className="py-2 text-sm text-muted-foreground"
          style={{ paddingLeft: `${depth * 20 + 28}px` }}
        >
          {t("emptyDirectory")}
        </div>
      )
    }

    return children.map((entry) => {
      const isExpanded = expandedPaths.has(entry.path)
      const isSelected = selectedPath === entry.path

      return (
        <div key={entry.path}>
          <button
            className={cn(
              "flex w-full items-center gap-1 rounded px-2 py-1 text-left text-sm transition-colors hover:bg-muted/50",
              isSelected && "bg-accent text-accent-foreground"
            )}
            style={{ paddingLeft: `${depth * 20 + 8}px` }}
            onClick={() => handleSelect(entry.path)}
            onDoubleClick={() => handleDoubleClick(entry.path)}
            type="button"
          >
            <span
              className="shrink-0 p-0.5"
              onClick={(e) => {
                e.stopPropagation()
                if (entry.hasChildren) {
                  handleToggleExpand(entry.path)
                }
              }}
              onKeyDown={(e) => {
                if (e.key === "Enter" || e.key === " ") {
                  e.stopPropagation()
                  if (entry.hasChildren) {
                    handleToggleExpand(entry.path)
                  }
                }
              }}
              role="button"
              tabIndex={0}
            >
              <ChevronRight
                className={cn(
                  "size-3.5 text-muted-foreground transition-transform",
                  isExpanded && "rotate-90",
                  !entry.hasChildren && "invisible"
                )}
              />
            </span>
            {isExpanded ? (
              <FolderOpenIcon className="size-4 shrink-0 text-blue-500" />
            ) : (
              <FolderIcon className="size-4 shrink-0 text-blue-500" />
            )}
            <span className="truncate">{entry.name}</span>
          </button>
          {isExpanded && renderEntries(entry.path, depth + 1)}
        </div>
      )
    })
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>{title ?? t("title")}</DialogTitle>
        </DialogHeader>

        <div className="space-y-3">
          <div className="flex items-center gap-1">
            <Button
              variant="ghost"
              size="icon"
              className="size-8 shrink-0"
              onClick={handleGoHome}
              title={t("goHome")}
              type="button"
            >
              <Home className="size-4" />
            </Button>
            <Button
              variant="ghost"
              size="icon"
              className="size-8 shrink-0"
              onClick={handleNavigateUp}
              title={t("navigateUp")}
              type="button"
            >
              <ChevronUp className="size-4" />
            </Button>
            <Input
              value={pathInput}
              onChange={(e) => setPathInput(e.target.value)}
              onKeyDown={handlePathInputKeyDown}
              placeholder={t("pathPlaceholder")}
              className="flex-1 h-8 text-sm font-mono"
            />
          </div>

          <ScrollArea className="h-[300px] rounded-md border">
            <div className="p-1">
              {renderEntries(rootPath, 0)}
              {error && !loading.size && (
                <div className="p-4 text-center text-sm text-destructive">
                  {error}
                </div>
              )}
            </div>
          </ScrollArea>

          {selectedPath && (
            <p className="truncate text-xs text-muted-foreground">
              {selectedPath}
            </p>
          )}
        </div>

        <DialogFooter>
          <Button
            variant="outline"
            onClick={() => onOpenChange(false)}
            type="button"
          >
            {t("cancel")}
          </Button>
          <Button
            onClick={handleConfirm}
            disabled={!selectedPath}
            type="button"
          >
            {t("select")}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
