import { useState, useCallback, useEffect } from "react";
import { cn } from "@/lib/utils";
import {
  X,
  Folder,
  File,
  RefreshCw,
  Plus,
  Trash2,
  Edit3,
  FolderPlus,
  Copy,
  Check,
  Loader2,
  Home,
  ChevronUp,
  Save,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { toast } from "sonner";

interface FileNode {
  name: string;
  path: string;
  isDirectory: boolean;
  size?: number;
}

interface FileManagerPanelProps {
  open: boolean;
  onClose: () => void;
}

// Language detection for syntax highlighting class
function getLanguage(name: string): string {
  const ext = name.split(".").pop()?.toLowerCase() || "";
  const langMap: Record<string, string> = {
    ts: "typescript",
    tsx: "tsx",
    js: "javascript",
    jsx: "jsx",
    json: "json",
    md: "markdown",
    css: "css",
    html: "html",
    py: "python",
    sh: "bash",
    yml: "yaml",
    yaml: "yaml",
    sql: "sql",
    env: "bash",
    toml: "toml",
    xml: "xml",
    svg: "xml",
    rs: "rust",
    go: "go",
    rb: "ruby",
    java: "java",
    c: "c",
    cpp: "cpp",
    h: "c",
    hpp: "cpp",
  };
  return langMap[ext] || "text";
}

// File icon color based on extension
function getFileColor(name: string) {
  const ext = name.split(".").pop()?.toLowerCase() || "";
  const colors: Record<string, string> = {
    ts: "text-blue-400",
    tsx: "text-blue-400",
    js: "text-yellow-400",
    jsx: "text-yellow-400",
    json: "text-green-400",
    md: "text-gray-400",
    css: "text-pink-400",
    html: "text-orange-400",
    py: "text-green-500",
    sh: "text-green-300",
    yml: "text-red-400",
    yaml: "text-red-400",
    sql: "text-cyan-400",
    env: "text-yellow-300",
    lock: "text-gray-500",
  };
  return colors[ext] || "text-muted-foreground";
}

export function FileManagerPanel({ open, onClose }: FileManagerPanelProps) {
  const [currentPath, setCurrentPath] = useState("/home/ubuntu");
  const [files, setFiles] = useState<FileNode[]>([]);
  const [loading, setLoading] = useState(false);
  const [selectedFile, setSelectedFile] = useState<string | null>(null);
  const [fileContent, setFileContent] = useState<string | null>(null);
  const [contentLoading, setContentLoading] = useState(false);
  const [creating, setCreating] = useState<"file" | "folder" | null>(null);
  const [newName, setNewName] = useState("");
  const [copied, setCopied] = useState(false);
  const [renaming, setRenaming] = useState<string | null>(null);
  const [renameValue, setRenameValue] = useState("");
  const [editing, setEditing] = useState(false);
  const [editContent, setEditContent] = useState("");

  // Fetch directory listing
  const fetchFiles = useCallback(async (dirPath: string) => {
    setLoading(true);
    try {
      const response = await fetch("/api/chat/slash", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          command: "/files",
          args: `list ${dirPath}`,
        }),
      });
      const data = await response.json();
      if (data.files) {
        setFiles(data.files);
      } else if (data.result) {
        const lines = data.result.split("\n").filter((l: string) => l.trim());
        const parsed: FileNode[] = lines
          .map((line: string) => {
            const isDir = line.endsWith("/");
            const name = isDir ? line.slice(0, -1) : line;
            return {
              name: name.split("/").pop() || name,
              path: `${dirPath}/${name.split("/").pop() || name}`,
              isDirectory: isDir,
            };
          })
          .filter((f: FileNode) => f.name);
        setFiles(parsed);
      }
    } catch {
      toast.error("Failed to load files");
    } finally {
      setLoading(false);
    }
  }, []);

  // Fetch file content
  const fetchFileContent = useCallback(async (filePath: string) => {
    setContentLoading(true);
    setSelectedFile(filePath);
    setEditing(false);
    try {
      const response = await fetch("/api/chat/slash", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          command: "/files",
          args: `read ${filePath}`,
        }),
      });
      const data = await response.json();
      const content = data.result || data.content || "(empty)";
      setFileContent(content);
      setEditContent(content);
    } catch {
      setFileContent("Error reading file");
    } finally {
      setContentLoading(false);
    }
  }, []);

  // Create file or folder
  const handleCreate = useCallback(async () => {
    if (!newName.trim()) return;
    const fullPath = `${currentPath}/${newName.trim()}`;
    try {
      const response = await fetch("/api/chat/slash", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          command: "/files",
          args: `${creating === "folder" ? "mkdir" : "touch"} ${fullPath}`,
        }),
      });
      const data = await response.json();
      toast.success(data.result || `Created ${newName}`);
      setCreating(null);
      setNewName("");
      fetchFiles(currentPath);
    } catch {
      toast.error("Failed to create");
    }
  }, [newName, currentPath, creating, fetchFiles]);

  // Delete file
  const handleDelete = useCallback(
    async (filePath: string) => {
      if (!confirm(`Delete ${filePath}?`)) return;
      try {
        const response = await fetch("/api/chat/slash", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            command: "/files",
            args: `delete ${filePath}`,
          }),
        });
        const data = await response.json();
        toast.success(data.result || "Deleted");
        fetchFiles(currentPath);
        if (selectedFile === filePath) {
          setSelectedFile(null);
          setFileContent(null);
        }
      } catch {
        toast.error("Failed to delete");
      }
    },
    [currentPath, selectedFile, fetchFiles]
  );

  // Rename file
  const handleRename = useCallback(
    async (oldPath: string) => {
      if (!renameValue.trim()) {
        setRenaming(null);
        return;
      }
      const dir = oldPath.substring(0, oldPath.lastIndexOf("/"));
      const newPath = `${dir}/${renameValue.trim()}`;
      try {
        const response = await fetch("/api/chat/slash", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            command: "/terminal",
            args: `${dir} mv "${oldPath}" "${newPath}"`,
          }),
        });
        const data = await response.json();
        if (data.error) {
          toast.error(data.error);
        } else {
          toast.success(`Renamed to ${renameValue}`);
          fetchFiles(currentPath);
          if (selectedFile === oldPath) {
            setSelectedFile(newPath);
          }
        }
      } catch {
        toast.error("Failed to rename");
      }
      setRenaming(null);
    },
    [renameValue, currentPath, selectedFile, fetchFiles]
  );

  // Save edited file
  const handleSaveFile = useCallback(async () => {
    if (!selectedFile) return;
    try {
      const response = await fetch("/api/chat/slash", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          command: "/terminal",
          args: `/home/ubuntu cat > "${selectedFile}" << 'CLAW_EOF'\n${editContent}\nCLAW_EOF`,
        }),
      });
      const data = await response.json();
      if (data.error) {
        toast.error(data.error);
      } else {
        toast.success("File saved!");
        setFileContent(editContent);
        setEditing(false);
      }
    } catch {
      toast.error("Failed to save file");
    }
  }, [selectedFile, editContent]);

  useEffect(() => {
    if (open) {
      fetchFiles(currentPath);
    }
  }, [open, currentPath, fetchFiles]);

  const copyContent = () => {
    if (fileContent) {
      navigator.clipboard.writeText(fileContent);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  };

  const navigateUp = () => {
    const parent = currentPath.split("/").slice(0, -1).join("/") || "/";
    setCurrentPath(parent);
  };

  // Breadcrumbs
  const pathParts = currentPath.split("/").filter(Boolean);

  if (!open) return null;

  return (
    <div className="fixed inset-0 z-50 flex">
      <div className="absolute inset-0 bg-black/50" onClick={onClose} />

      <div className="relative ml-auto w-full max-w-3xl bg-background border-l border-border flex flex-col h-full shadow-2xl">
        {/* Header */}
        <div className="flex items-center justify-between px-4 py-3 border-b border-border">
          <div className="flex items-center gap-2">
            <Folder className="size-4 text-primary" />
            <h2 className="text-sm font-semibold">File Manager</h2>
          </div>
          <button
            onClick={onClose}
            className="size-7 rounded-md hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground transition-colors"
          >
            <X className="size-4" />
          </button>
        </div>

        {/* Breadcrumb path bar */}
        <div className="flex items-center gap-1 px-4 py-2 border-b border-border bg-secondary/20 overflow-x-auto">
          <button
            onClick={() => setCurrentPath("/")}
            className="size-6 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground shrink-0"
          >
            <Home className="size-3.5" />
          </button>
          {pathParts.map((part, i) => {
            const path = "/" + pathParts.slice(0, i + 1).join("/");
            return (
              <div key={path} className="flex items-center gap-1">
                <span className="text-muted-foreground/40 text-xs">/</span>
                <button
                  onClick={() => setCurrentPath(path)}
                  className={cn(
                    "text-xs font-mono px-1 py-0.5 rounded hover:bg-accent transition-colors",
                    i === pathParts.length - 1
                      ? "text-foreground font-medium"
                      : "text-muted-foreground"
                  )}
                >
                  {part}
                </button>
              </div>
            );
          })}
          <div className="flex-1" />
          <div className="flex items-center gap-1 shrink-0">
            <button
              onClick={navigateUp}
              className="size-6 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground"
              title="Go up"
            >
              <ChevronUp className="size-3.5" />
            </button>
            <button
              onClick={() => setCreating("file")}
              className="size-6 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground"
              title="New file"
            >
              <Plus className="size-3.5" />
            </button>
            <button
              onClick={() => setCreating("folder")}
              className="size-6 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground"
              title="New folder"
            >
              <FolderPlus className="size-3.5" />
            </button>
            <button
              onClick={() => fetchFiles(currentPath)}
              className="size-6 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground"
              title="Refresh"
            >
              <RefreshCw className="size-3.5" />
            </button>
          </div>
        </div>

        {/* Create form */}
        {creating && (
          <div className="px-4 py-2 border-b border-border bg-accent/20 flex items-center gap-2">
            <span className="text-xs text-muted-foreground">
              New {creating}:
            </span>
            <Input
              value={newName}
              onChange={(e) => setNewName(e.target.value)}
              placeholder={creating === "folder" ? "folder-name" : "file.txt"}
              className="h-7 text-xs font-mono flex-1"
              autoFocus
              onKeyDown={(e) => {
                if (e.key === "Enter") handleCreate();
                if (e.key === "Escape") {
                  setCreating(null);
                  setNewName("");
                }
              }}
            />
            <Button size="sm" className="h-7 text-xs" onClick={handleCreate}>
              Create
            </Button>
            <button
              onClick={() => {
                setCreating(null);
                setNewName("");
              }}
              className="text-muted-foreground hover:text-foreground"
            >
              <X className="size-3.5" />
            </button>
          </div>
        )}

        {/* Content area */}
        <div className="flex-1 flex overflow-hidden">
          {/* File list */}
          <div className="w-1/3 border-r border-border overflow-y-auto">
            {loading ? (
              <div className="flex items-center justify-center py-8">
                <Loader2 className="size-4 animate-spin text-muted-foreground" />
              </div>
            ) : files.length === 0 ? (
              <div className="text-xs text-muted-foreground text-center py-8">
                Empty directory
              </div>
            ) : (
              <div className="py-1">
                {files
                  .sort((a, b) => {
                    if (a.isDirectory && !b.isDirectory) return -1;
                    if (!a.isDirectory && b.isDirectory) return 1;
                    return a.name.localeCompare(b.name);
                  })
                  .map((file) => (
                    <div
                      key={file.path}
                      className={cn(
                        "group flex items-center gap-2 px-3 py-1.5 cursor-pointer transition-colors",
                        selectedFile === file.path
                          ? "bg-accent text-accent-foreground"
                          : "hover:bg-accent/50"
                      )}
                      onClick={() => {
                        if (file.isDirectory) {
                          setCurrentPath(file.path);
                          setSelectedFile(null);
                          setFileContent(null);
                        } else {
                          fetchFileContent(file.path);
                        }
                      }}
                    >
                      {file.isDirectory ? (
                        <Folder className="size-3.5 text-yellow-400 shrink-0" />
                      ) : (
                        <File
                          className={cn(
                            "size-3.5 shrink-0",
                            getFileColor(file.name)
                          )}
                        />
                      )}

                      {renaming === file.path ? (
                        <input
                          value={renameValue}
                          onChange={(e) => setRenameValue(e.target.value)}
                          onKeyDown={(e) => {
                            if (e.key === "Enter") handleRename(file.path);
                            if (e.key === "Escape") setRenaming(null);
                          }}
                          onBlur={() => handleRename(file.path)}
                          className="flex-1 bg-background text-xs rounded px-1.5 py-0.5 outline-none border border-border font-mono"
                          autoFocus
                          onClick={(e) => e.stopPropagation()}
                        />
                      ) : (
                        <span className="text-xs truncate flex-1 font-mono">
                          {file.name}
                        </span>
                      )}

                      <div className="hidden group-hover:flex items-center gap-0.5 shrink-0">
                        <button
                          onClick={(e) => {
                            e.stopPropagation();
                            setRenaming(file.path);
                            setRenameValue(file.name);
                          }}
                          className="size-5 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground"
                          title="Rename"
                        >
                          <Edit3 className="size-3" />
                        </button>
                        <button
                          onClick={(e) => {
                            e.stopPropagation();
                            handleDelete(file.path);
                          }}
                          className="size-5 rounded hover:bg-destructive/20 flex items-center justify-center text-destructive"
                          title="Delete"
                        >
                          <Trash2 className="size-3" />
                        </button>
                      </div>
                    </div>
                  ))}
              </div>
            )}
          </div>

          {/* File content viewer */}
          <div className="flex-1 flex flex-col overflow-hidden">
            {selectedFile ? (
              <>
                <div className="flex items-center justify-between px-3 py-2 border-b border-border bg-secondary/20">
                  <div className="flex items-center gap-2 min-w-0">
                    <span className="text-xs font-mono text-muted-foreground truncate">
                      {selectedFile.split("/").pop()}
                    </span>
                    <span className="text-[10px] text-muted-foreground/50 bg-secondary/50 px-1.5 py-0.5 rounded">
                      {getLanguage(selectedFile)}
                    </span>
                  </div>
                  <div className="flex items-center gap-1 shrink-0">
                    {editing ? (
                      <button
                        onClick={handleSaveFile}
                        className="size-6 rounded hover:bg-accent flex items-center justify-center text-green-400 hover:text-green-300"
                        title="Save"
                      >
                        <Save className="size-3.5" />
                      </button>
                    ) : (
                      <button
                        onClick={() => {
                          setEditing(true);
                          setEditContent(fileContent || "");
                        }}
                        className="size-6 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground"
                        title="Edit"
                      >
                        <Edit3 className="size-3.5" />
                      </button>
                    )}
                    <button
                      onClick={copyContent}
                      className="size-6 rounded hover:bg-accent flex items-center justify-center text-muted-foreground hover:text-foreground transition-colors"
                      title="Copy"
                    >
                      {copied ? (
                        <Check className="size-3.5 text-green-400" />
                      ) : (
                        <Copy className="size-3.5" />
                      )}
                    </button>
                  </div>
                </div>
                <div className="flex-1 overflow-auto">
                  {contentLoading ? (
                    <div className="flex items-center justify-center py-8">
                      <Loader2 className="size-4 animate-spin text-muted-foreground" />
                    </div>
                  ) : editing ? (
                    <textarea
                      value={editContent}
                      onChange={(e) => setEditContent(e.target.value)}
                      className="w-full h-full bg-background text-xs font-mono text-foreground/90 p-3 outline-none resize-none leading-relaxed"
                      spellCheck={false}
                    />
                  ) : (
                    <div className="relative">
                      {/* Line numbers + content */}
                      <div className="flex text-xs font-mono leading-relaxed">
                        <div className="select-none text-right pr-3 pl-2 py-3 text-muted-foreground/30 border-r border-border/50 bg-secondary/10 shrink-0">
                          {(fileContent || "")
                            .split("\n")
                            .map((_, i) => (
                              <div key={i}>{i + 1}</div>
                            ))}
                        </div>
                        <pre className="flex-1 p-3 text-foreground/80 whitespace-pre-wrap break-all overflow-x-auto">
                          {fileContent}
                        </pre>
                      </div>
                    </div>
                  )}
                </div>
              </>
            ) : (
              <div className="flex-1 flex flex-col items-center justify-center text-muted-foreground gap-2">
                <File className="size-8 opacity-20" />
                <span className="text-xs">Select a file to view</span>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
