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);
  const [historyIndex, setHistoryIndex] = useState(-1);

  // 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;
    } else if (e.key === "ArrowDown") {
      e.preventDefault();
      navigateHistory(-1);
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      navigateHistory(1);
    }
  };

  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",
        "tree",
      ];
      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", "tree"].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;

    setHistoryIndex(-1);
    // 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" +
          "  tree [directory] - Display directory structure\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;
      case "tree":
        output = handleTree(args);
        break;
      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;
    let showHidden = false;
    let pathArgs = [];

    // Parse arguments
    args.forEach((arg) => {
      if (arg.startsWith("-")) {
        // Handle flags
        if (arg === "-a" || arg === "--all") {
          showHidden = true;
        } else if (arg === "--help") {
          return `Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically.

  -a, --all    do not ignore entries starting with .
  --help       display this help and exit`;
        }
      } else {
        // It's a path argument
        pathArgs.push(arg);
      }
    });

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

    const item = getItemAtPath(targetPath);

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

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

    // Get and filter children based on showHidden flag
    const children = Object.keys(item.children)
      .filter((name) => showHidden || !name.startsWith("."))
      .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];
    let targetPath = fileName;

    // If it's not an absolute path, resolve it relative to current directory
    if (!fileName.startsWith("/")) {
      targetPath = resolvePath(fileName);
    }

    // Get the directory and file name from the path
    const lastSlashIndex = targetPath.lastIndexOf("/");
    const dirPath =
      lastSlashIndex === -1
        ? currentPath
        : targetPath.substring(0, lastSlashIndex);
    const targetFileName =
      lastSlashIndex === -1
        ? targetPath
        : targetPath.substring(lastSlashIndex + 1);

    const dir = getItemAtPath(dirPath);

    if (!dir || dir.type !== "directory") {
      return `cat: ${fileName}: No such file or directory`;
    }

    const file = dir.children[targetFileName];
    if (!file || file.type !== "file") {
      return `cat: ${fileName}: No such file`;
    }

    return file.content;
  };

  // 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>`;
  };

  // Add tree command handler
  const handleTree = (args) => {
    const path = args[0] || currentPath;
    const resolvedPath = resolvePath(path);
    const item = getItemAtPath(resolvedPath);

    if (!item) {
      return `tree: ${path}: No such directory`;
    }

    if (item.type !== "directory") {
      return `tree: ${path}: Not a directory`;
    }

    const output = [];
    const printTree = (node, name, prefix = "", isLast = true) => {
      const isDir = node.type === "directory";
      const icon = isDir ? "📁" : "📄";

      output.push(`${prefix}${isLast ? "└── " : "├── "}${icon} ${name}`);

      if (isDir && node.children) {
        const entries = Object.entries(node.children);
        entries.forEach(([key, value], index) => {
          const isLastEntry = index === entries.length - 1;
          const newPrefix = prefix + (isLast ? "    " : "│   ");
          printTree(value, key, newPrefix, isLastEntry);
        });
      }
    };

    // Start with the root directory name
    const rootName = resolvedPath.split("/").pop() || "/";
    printTree(item, rootName);
    return output.join("\n");
  };

  // Function to navigate command history
  const navigateHistory = (direction) => {
    if (commandHistory.length === 0) return;

    const newIndex = historyIndex + direction;
    if (newIndex >= -1 && newIndex < commandHistory.length) {
      setHistoryIndex(newIndex);
      if (newIndex === -1) {
        setInputValue("");
      } else {
        setInputValue(
          commandHistory[commandHistory.length - 1 - newIndex].command
        );
      }
    }
  };

  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">
            <div className="text-purple-300 gothic-text text-4xl tracking-wider">
              NPC ABOUT ME
            </div>
            <div className="text-green-400 gothic-text font-semibold mb-2 text-2xl">
              Welcome to my interactive terminal!
            </div>
            <div className="text-amber-300 gothic-text mb-3 text-xl">
              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 gothic-text text-xl">
                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 gothic-text text-xl">
              <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>
  );
}
