import { useState, useEffect, useRef } from "react";
import { fileSystem } from "../data/filesystem";

export default function Terminal() {
  const [currentPath, setCurrentPath] = useState("/home/guest");
  const [commandHistory, setCommandHistory] = useState([]);
  const [inputValue, setInputValue] = useState("");
  const inputRef = useRef(null);
  const terminalRef = useRef(null);
  const [hasBeenCleared, setHasBeenCleared] = useState(false);

  // Focus the input when the component mounts and on click
  useEffect(() => {
    inputRef.current.focus();
  }, []);

  useEffect(() => {
    // Make sure input is focused after render
    if (inputRef.current) {
      inputRef.current.focus();
    }
  }, [commandHistory]); // Re-focus after command history changes

  const focusInput = () => {
    inputRef.current.focus();
  };

  const handleKeyDown = (e) => {
    console.log("Key pressed:", e.key, "Input value:", inputValue); // Add debugging

    if (e.key === "Enter") {
      e.preventDefault();
      e.stopPropagation(); // Stop event propagation
      console.log("Enter pressed, executing command:", inputValue);
      executeCommand();
      return false; // Ensure the event is fully handled
    } else if (e.key === "Tab") {
      e.preventDefault();
      handleTabCompletion();
    } else if (e.key === "l" && e.ctrlKey) {
      e.preventDefault();
      handleClear();
      setInputValue("");
      return;
    }
  };

  const handleContainerKeyDown = (e) => {
    if (e.key === "Enter" && document.activeElement === inputRef.current) {
      e.preventDefault();
      executeCommand();
    }
  };

  const handleClear = () => {
    setCommandHistory([]);
    setHasBeenCleared(true);

    // Return focus to input
    setTimeout(() => {
      if (inputRef.current) {
        inputRef.current.focus();
      }
    }, 10);

    return "";
  };

  // Path resolution functions
  const resolvePath = (path) => {
    // If it's an absolute path, start from root
    if (path.startsWith("/")) {
      return path;
    }

    // If it's ".", return current path
    if (path === ".") {
      return currentPath;
    }

    // If it's "..", go up one level
    if (path === "..") {
      const pathParts = currentPath.split("/").filter(Boolean);
      if (pathParts.length === 0) {
        return "/";
      }
      pathParts.pop();
      return "/" + pathParts.join("/");
    }

    // Handle relative paths - append to current path
    if (currentPath.endsWith("/")) {
      return currentPath + path;
    }
    return currentPath + "/" + path;
  };

  const getItemAtPath = (path) => {
    const normalizedPath =
      path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;

    if (normalizedPath === "/") {
      return fileSystem["/"];
    }

    const pathParts = normalizedPath.split("/").filter(Boolean);
    let current = fileSystem["/"];

    for (const part of pathParts) {
      if (!current || current.type !== "directory" || !current.children[part]) {
        return null;
      }
      current = current.children[part];
    }

    return current;
  };

  // Handle tab completion
  const handleTabCompletion = () => {
    if (!inputValue.trim()) return;

    const parts = inputValue.trim().split(" ");
    const command = parts[0].toLowerCase();

    // If completing a command
    if (parts.length === 1) {
      const commands = [
        "ls",
        "cd",
        "cat",
        "pwd",
        "date",
        "help",
        "clear",
        "view",
      ];
      const matchingCommands = commands.filter((cmd) =>
        cmd.startsWith(command)
      );

      if (matchingCommands.length === 1) {
        setInputValue(matchingCommands[0]);
      }
      return;
    }

    // If completing a path/file/directory
    if (["cd", "cat", "ls", "view"].includes(command)) {
      const partialPath = parts[parts.length - 1];
      const suggestions = getPathSuggestions(partialPath);

      if (suggestions.length === 1) {
        const completedParts = [...parts];
        completedParts[completedParts.length - 1] = suggestions[0];
        setInputValue(completedParts.join(" "));
      }
    }
  };

  // Get path suggestions based on current directory
  const getPathSuggestions = (partialPath) => {
    const dirPath = partialPath.includes("/")
      ? partialPath.substring(0, partialPath.lastIndexOf("/") + 1)
      : "";

    const prefix = partialPath.includes("/")
      ? partialPath.substring(partialPath.lastIndexOf("/") + 1)
      : partialPath;

    const resolvedDirPath = resolvePath(dirPath || currentPath);
    const dir = getItemAtPath(resolvedDirPath);

    if (!dir || dir.type !== "directory") return [];

    return Object.keys(dir.children)
      .filter((name) => name.startsWith(prefix))
      .map((name) => {
        const fullPath = dirPath + name;
        if (dir.children[name].type === "directory") {
          return fullPath + "/";
        }
        return fullPath;
      });
  };

  // Process and execute commands
  const executeCommand = () => {
    if (!inputValue.trim()) return;

    // Create a new history entry with the CURRENT PATH at execution time
    const newHistoryEntry = {
      command: inputValue,
      output: "",
      path: currentPath, // Store the path at execution time
    };

    const parts = inputValue.trim().split(/\s+/);
    const command = parts[0].toLowerCase();
    const args = parts.slice(1);

    let output = "";

    switch (command) {
      case "ls":
        output = handleLs(args);
        break;
      case "cd":
        output = handleCd(args);
        break;
      case "cat":
        output = handleCat(args);
        break;
      case "view":
        output = handleView(args);
        break;
      case "pwd":
        output = currentPath;
        break;
      case "date":
        output = new Date().toLocaleString();
        break;
      case "help":
        output =
          "Available commands:\n" +
          "  ls - List directory contents\n" +
          "  cd [directory] - Change directory\n" +
          "  cat [file] - Display file contents\n" +
          "  view [image] - Display image files\n" +
          "  pwd - Print working directory\n" +
          "  clear - Clear the terminal\n" +
          "  help - Display this help message\n\n" +
          "Shortcuts:\n" +
          "  Tab - Autocomplete commands and paths\n" +
          "  Ctrl+L - Clear the terminal";
        break;
      case "clear":
        clearTerminal();
        setInputValue("");
        return;
      default:
        output = `Command not found: ${command}`;
    }

    newHistoryEntry.output = output;
    setCommandHistory([...commandHistory, newHistoryEntry]);
    setInputValue("");

    // Auto-scroll to bottom and re-focus input after rendering
    setTimeout(() => {
      if (terminalRef.current) {
        terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
      }
      if (inputRef.current) {
        inputRef.current.focus();
      }
    }, 50);
  };

  // Handle ls command
  const handleLs = (args) => {
    let targetPath = currentPath;

    if (args.length > 0) {
      // Handle path argument
      targetPath = resolvePath(args[0]);
    }

    const item = getItemAtPath(targetPath);

    if (!item) {
      return `ls: ${args[0]}: No such file or directory`;
    }

    if (item.type !== "directory") {
      return `ls: ${args[0]}: Not a directory`;
    }

    const children = Object.keys(item.children).sort();

    if (children.length === 0) {
      return "<span class='text-gray-400'>Empty directory</span>";
    }

    return children
      .map((name) => {
        const child = item.children[name];
        const itemClass =
          child.type === "directory"
            ? "directory"
            : child.type === "image"
            ? "image"
            : "file";

        return `<div class="file-item ${itemClass}">${name}</div>`;
      })
      .join("");
  };

  // Handle cd command
  const handleCd = (args) => {
    if (!args.length || args[0] === "~" || args[0] === "/home/guest") {
      setCurrentPath("/home/guest");
      return "";
    }

    // Handle special case for tilde expansion
    let targetPath = args[0];
    if (targetPath.startsWith("~/")) {
      targetPath = "/home/guest/" + targetPath.substring(2);
    } else if (targetPath === "~") {
      targetPath = "/home/guest";
    }

    let newPath = resolvePath(targetPath);

    // Ensure path has leading slash
    if (!newPath.startsWith("/")) {
      newPath = "/" + newPath;
    }

    // Normalize path (remove trailing slash except for root)
    if (newPath !== "/" && newPath.endsWith("/")) {
      newPath = newPath.slice(0, -1);
    }

    const targetDir = getItemAtPath(newPath);

    if (!targetDir) {
      return `cd: ${targetPath}: No such directory`;
    }

    if (targetDir.type !== "directory") {
      return `cd: ${targetPath}: Not a directory`;
    }

    setCurrentPath(newPath);
    return "";
  };

  // Handle cat command
  const handleCat = (args) => {
    if (!args.length) {
      return "Usage: cat [filename]";
    }

    const fileName = args[0];
    const currentDir = getItemAtPath(currentPath);

    if (!currentDir || currentDir.type !== "directory") {
      return "Current location is not a directory";
    }

    if (
      fileName in currentDir.children &&
      currentDir.children[fileName].type === "file"
    ) {
      return currentDir.children[fileName].content;
    }

    return `cat: ${fileName}: No such file`;
  };

  // Handle view command for images
  const handleView = (args) => {
    if (!args.length) {
      return "Usage: view [image filename]";
    }

    const fileName = args[0];
    let file;

    // Handle paths with slashes
    if (fileName.includes("/")) {
      const path = resolvePath(fileName);
      file = getItemAtPath(path);
    } else {
      // Look in current directory
      const currentDir = getItemAtPath(currentPath);
      if (!currentDir || currentDir.type !== "directory") {
        return "Current location is not a directory";
      }

      file = currentDir.children[fileName];
    }

    if (!file) {
      return `view: ${fileName}: No such file`;
    }

    if (file.type !== "image") {
      return `view: ${fileName}: Not an image file`;
    }

    // Return HTML with the image
    setTimeout(() => {
      // Re-focus the input after image is displayed
      if (inputRef.current) {
        inputRef.current.focus();
      }
    }, 50);

    return `<div class="mt-2 flex flex-col items-center">
      <img src="${file.src}" alt="${file.description || "Image"}" 
           class="max-w-full rounded shadow-md" style="max-height: 300px;" />
      <div class="text-sm text-gray-400 mt-1">${file.description || ""}</div>
    </div>`;
  };

  return (
    <div
      className="h-full text-terminal-text font-mono p-4 overflow-hidden flex flex-col text-left bg-gradient-to-b from-gray-900 to-black rounded-b-lg"
      onClick={focusInput}
      onKeyDown={handleContainerKeyDown}
      tabIndex="-1"
    >
      <div
        ref={terminalRef}
        className="flex-1 overflow-y-auto overflow-x-hidden pb-4 custom-scrollbar text-left"
        style={{
          maxHeight: "calc(100% - 30px)",
          scrollbarWidth: "thin",
          scrollbarColor: "rgba(128, 90, 213, 0.7) rgba(35, 35, 35, 0.5)",
        }}
      >
        {!hasBeenCleared && (
          <div className="text-lg mb-4 text-terminal-accent text-left">
            <pre className="text-purple-300 font-bold">
              {`
 _   _ ____   ____      _    ____   ___  _   _ _____      __  __ _____ 
| \\ | |  _ \\ / ___|    / \\  | __ ) / _ \\| | | |_   _|    |  \\/  | ____|
|  \\| | |_) | |       / _ \\ |  _ \\| | | | | | | | |      | |\\/| |  _|  
| |\\  |  __/| |___   / ___ \\| |_) | |_| | |_| | | |      | |  | | |___ 
|_| \\_|_|    \\____| /_/   \\_\\____/ \\___/ \\___/  |_|      |_|  |_|_____|
                                                                        
`}
            </pre>
            <div className="text-green-400 font-semibold mb-2">
              Welcome to my interactive terminal!
            </div>
            <div className="text-amber-300 mb-3">
              Type{" "}
              <span className="bg-gray-800 px-1 rounded text-white">help</span>{" "}
              to see available commands.
            </div>
          </div>
        )}

        {commandHistory.map((entry, index) => (
          <div key={index} className="mb-2 text-left">
            <div className="flex">
              <span className="text-terminal-prompt mr-2">
                guest@npc-shell:
                {entry.path === "/home/guest"
                  ? "~"
                  : entry.path.replace("/home/guest", "~")}
                $
              </span>
              <span className="text-terminal-command">{entry.command}</span>
            </div>
            {entry.output && (
              <div
                className={`mt-1 text-left terminal-content ${
                  entry.command.startsWith("ls")
                    ? "command-output-ls"
                    : "whitespace-pre-line"
                }`}
                dangerouslySetInnerHTML={{ __html: entry.output }}
              />
            )}
          </div>
        ))}

        <form
          onSubmit={(e) => {
            e.preventDefault();
            executeCommand();
          }}
          className="w-full"
        >
          <div className="flex items-center">
            <span className="text-terminal-prompt mr-2 flex items-center">
              <span className="text-green-400">guest</span>
              <span className="text-gray-500">@</span>
              <span className="text-purple-400">npc-shell</span>
              <span className="text-gray-500">:</span>
              <span className="text-blue-400">
                {currentPath === "/home/guest"
                  ? "~"
                  : currentPath.replace("/home/guest", "~")}
              </span>
              <span className="text-yellow-500">$</span>
            </span>
            <input
              ref={inputRef}
              className="bg-transparent text-terminal-command outline-none border-none flex-1 caret-purple-400"
              type="text"
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
              onKeyDown={handleKeyDown}
              autoComplete="off"
              spellCheck="false"
            />
          </div>
        </form>
      </div>
    </div>
  );
}
