
import { useState, useEffect, useRef, useCallback } from "react";
import {
  FolderOpen,
  Folder,
  ChevronRight,
  Home,
  ArrowLeft,
  HardDrive,
  CornerDownLeft,
  Clock,
  X,
} from "lucide-react";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

interface DirectoryEntry {
  name: string;
  path: string;
}

interface BrowseResult {
  success: boolean;
  currentPath: string;
  parentPath: string | null;
  directories: DirectoryEntry[];
  drives?: string[];
  error?: string;
  warning?: string;
}

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

const RECENT_FOLDERS_KEY = "file-browser-recent-folders";
const MAX_RECENT_FOLDERS = 5;

function getRecentFolders(): string[] {
  if (typeof window === "undefined") return [];
  try {
    const stored = localStorage.getItem(RECENT_FOLDERS_KEY);
    return stored ? JSON.parse(stored) : [];
  } catch {
    return [];
  }
}

function addRecentFolder(path: string): void {
  if (typeof window === "undefined") return;
  try {
    const recent = getRecentFolders();
    // Remove if already exists, then add to front
    const filtered = recent.filter((p) => p !== path);
    const updated = [path, ...filtered].slice(0, MAX_RECENT_FOLDERS);
    localStorage.setItem(RECENT_FOLDERS_KEY, JSON.stringify(updated));
  } catch {
    // Ignore localStorage errors
  }
}

function removeRecentFolder(path: string): string[] {
  if (typeof window === "undefined") return [];
  try {
    const recent = getRecentFolders();
    const updated = recent.filter((p) => p !== path);
    localStorage.setItem(RECENT_FOLDERS_KEY, JSON.stringify(updated));
    return updated;
  } catch {
    return [];
  }
}

export function FileBrowserDialog({
  open,
  onOpenChange,
  onSelect,
  title = "Select Project Directory",
  description = "Navigate to your project folder or paste a path directly",
  initialPath,
}: FileBrowserDialogProps) {
  const [currentPath, setCurrentPath] = useState<string>("");
  const [pathInput, setPathInput] = useState<string>("");
  const [parentPath, setParentPath] = useState<string | null>(null);
  const [directories, setDirectories] = useState<DirectoryEntry[]>([]);
  const [drives, setDrives] = useState<string[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [warning, setWarning] = useState("");
  const [recentFolders, setRecentFolders] = useState<string[]>([]);
  const pathInputRef = useRef<HTMLInputElement>(null);

  // Load recent folders when dialog opens
  useEffect(() => {
    if (open) {
      setRecentFolders(getRecentFolders());
    }
  }, [open]);

  const handleRemoveRecent = useCallback((e: React.MouseEvent, path: string) => {
    e.stopPropagation();
    const updated = removeRecentFolder(path);
    setRecentFolders(updated);
  }, []);

  const handleSelectRecent = useCallback((path: string) => {
    browseDirectory(path);
  }, []);

  const browseDirectory = async (dirPath?: string) => {
    setLoading(true);
    setError("");
    setWarning("");

    try {
      // Get server URL from environment or default
      const serverUrl =
        import.meta.env.VITE_SERVER_URL || "http://localhost:3008";

      const response = await fetch(`${serverUrl}/api/fs/browse`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ dirPath }),
      });

      const result: BrowseResult = await response.json();

      if (result.success) {
        setCurrentPath(result.currentPath);
        setPathInput(result.currentPath);
        setParentPath(result.parentPath);
        setDirectories(result.directories);
        setDrives(result.drives || []);
        setWarning(result.warning || "");
      } else {
        setError(result.error || "Failed to browse directory");
      }
    } catch (err) {
      setError(
        err instanceof Error ? err.message : "Failed to load directories"
      );
    } finally {
      setLoading(false);
    }
  };

  // Reset current path when dialog closes
  useEffect(() => {
    if (!open) {
      setCurrentPath("");
      setPathInput("");
      setParentPath(null);
      setDirectories([]);
      setError("");
      setWarning("");
    }
  }, [open]);

  // Load initial path or home directory when dialog opens
  useEffect(() => {
    if (open && !currentPath) {
      browseDirectory(initialPath);
    }
  }, [open, initialPath]);

  const handleSelectDirectory = (dir: DirectoryEntry) => {
    browseDirectory(dir.path);
  };

  const handleGoToParent = () => {
    if (parentPath) {
      browseDirectory(parentPath);
    }
  };

  const handleGoHome = () => {
    browseDirectory();
  };

  const handleSelectDrive = (drivePath: string) => {
    browseDirectory(drivePath);
  };

  const handleGoToPath = () => {
    const trimmedPath = pathInput.trim();
    if (trimmedPath) {
      browseDirectory(trimmedPath);
    }
  };

  const handlePathInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      e.preventDefault();
      handleGoToPath();
    }
  };

  const handleSelect = () => {
    if (currentPath) {
      addRecentFolder(currentPath);
      onSelect(currentPath);
      onOpenChange(false);
    }
  };

  // Helper to get folder name from path
  const getFolderName = (path: string) => {
    const parts = path.split(/[/\\]/).filter(Boolean);
    return parts[parts.length - 1] || path;
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="bg-popover border-border max-w-3xl max-h-[85vh] overflow-hidden flex flex-col p-4">
        <DialogHeader className="pb-1">
          <DialogTitle className="flex items-center gap-2 text-base">
            <FolderOpen className="w-4 h-4 text-brand-500" />
            {title}
          </DialogTitle>
          <DialogDescription className="text-muted-foreground text-xs">
            {description}
          </DialogDescription>
        </DialogHeader>

        <div className="flex flex-col gap-2 min-h-[350px] flex-1 overflow-hidden py-1">
          {/* Direct path input */}
          <div className="flex items-center gap-1.5">
            <Input
              ref={pathInputRef}
              type="text"
              placeholder="Paste or type a full path (e.g., /home/user/projects/myapp)"
              value={pathInput}
              onChange={(e) => setPathInput(e.target.value)}
              onKeyDown={handlePathInputKeyDown}
              className="flex-1 font-mono text-xs h-8"
              data-testid="path-input"
              disabled={loading}
            />
            <Button
              variant="secondary"
              size="sm"
              onClick={handleGoToPath}
              disabled={loading || !pathInput.trim()}
              data-testid="go-to-path-button"
              className="h-8 px-2"
            >
              <CornerDownLeft className="w-3.5 h-3.5 mr-1" />
              Go
            </Button>
          </div>

          {/* Recent folders */}
          {recentFolders.length > 0 && (
            <div className="flex flex-wrap gap-1.5 p-2 rounded-md bg-sidebar-accent/10 border border-sidebar-border">
              <div className="flex items-center gap-1 text-xs text-muted-foreground mr-1">
                <Clock className="w-3 h-3" />
                <span>Recent:</span>
              </div>
              {recentFolders.map((folder) => (
                <button
                  key={folder}
                  onClick={() => handleSelectRecent(folder)}
                  className="group flex items-center gap-1 h-6 px-2 text-xs bg-sidebar-accent/20 hover:bg-sidebar-accent/40 rounded border border-sidebar-border transition-colors"
                  disabled={loading}
                  title={folder}
                >
                  <Folder className="w-3 h-3 text-brand-500 shrink-0" />
                  <span className="truncate max-w-[120px]">{getFolderName(folder)}</span>
                  <button
                    onClick={(e) => handleRemoveRecent(e, folder)}
                    className="ml-0.5 opacity-0 group-hover:opacity-100 hover:text-destructive transition-opacity"
                    title="Remove from recent"
                  >
                    <X className="w-3 h-3" />
                  </button>
                </button>
              ))}
            </div>
          )}

          {/* Drives selector (Windows only) */}
          {drives.length > 0 && (
            <div className="flex flex-wrap gap-1.5 p-2 rounded-md bg-sidebar-accent/10 border border-sidebar-border">
              <div className="flex items-center gap-1 text-xs text-muted-foreground mr-1">
                <HardDrive className="w-3 h-3" />
                <span>Drives:</span>
              </div>
              {drives.map((drive) => (
                <Button
                  key={drive}
                  variant={
                    currentPath.startsWith(drive) ? "default" : "outline"
                  }
                  size="sm"
                  onClick={() => handleSelectDrive(drive)}
                  className="h-6 px-2 text-xs"
                  disabled={loading}
                >
                  {drive.replace("\\", "")}
                </Button>
              ))}
            </div>
          )}

          {/* Current path breadcrumb */}
          <div className="flex items-center gap-1.5 p-2 rounded-md bg-sidebar-accent/10 border border-sidebar-border">
            <Button
              variant="ghost"
              size="sm"
              onClick={handleGoHome}
              className="h-6 px-1.5"
              disabled={loading}
            >
              <Home className="w-3.5 h-3.5" />
            </Button>
            {parentPath && (
              <Button
                variant="ghost"
                size="sm"
                onClick={handleGoToParent}
                className="h-6 px-1.5"
                disabled={loading}
              >
                <ArrowLeft className="w-3.5 h-3.5" />
              </Button>
            )}
            <div className="flex-1 font-mono text-xs truncate text-muted-foreground">
              {currentPath || "Loading..."}
            </div>
          </div>

          {/* Directory list */}
          <div className="flex-1 overflow-y-auto border border-sidebar-border rounded-md">
            {loading && (
              <div className="flex items-center justify-center h-full p-4">
                <div className="text-xs text-muted-foreground">
                  Loading directories...
                </div>
              </div>
            )}

            {error && (
              <div className="flex items-center justify-center h-full p-4">
                <div className="text-xs text-destructive">{error}</div>
              </div>
            )}

            {warning && (
              <div className="p-2 bg-yellow-500/10 border border-yellow-500/30 rounded-md mb-1">
                <div className="text-xs text-yellow-500">{warning}</div>
              </div>
            )}

            {!loading && !error && !warning && directories.length === 0 && (
              <div className="flex items-center justify-center h-full p-4">
                <div className="text-xs text-muted-foreground">
                  No subdirectories found
                </div>
              </div>
            )}

            {!loading && !error && directories.length > 0 && (
              <div className="divide-y divide-sidebar-border">
                {directories.map((dir) => (
                  <button
                    key={dir.path}
                    onClick={() => handleSelectDirectory(dir)}
                    className="w-full flex items-center gap-2 px-2 py-1.5 hover:bg-sidebar-accent/10 transition-colors text-left group"
                  >
                    <Folder className="w-4 h-4 text-brand-500 shrink-0" />
                    <span className="flex-1 truncate text-xs">{dir.name}</span>
                    <ChevronRight className="w-3.5 h-3.5 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity shrink-0" />
                  </button>
                ))}
              </div>
            )}
          </div>

          <div className="text-[10px] text-muted-foreground">
            Paste a full path above, or click on folders to navigate. Press
            Enter or click Go to jump to a path.
          </div>
        </div>

        <DialogFooter className="border-t border-border pt-3 gap-2 mt-1">
          <Button variant="ghost" size="sm" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button size="sm" onClick={handleSelect} disabled={!currentPath || loading}>
            <FolderOpen className="w-3.5 h-3.5 mr-1.5" />
            Select Current Folder
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
