import { useState, useEffect, useRef } from "preact/hooks";
import type { JSX } from "preact";
import type { Command } from "../utils/terminal/types";
import { buildFileSystem } from "../utils/terminal/fs";
import {
  executeCommand,
  type CommandContext,
} from "../utils/terminal/commands";
import {
  getCompletions,
  formatOutput,
  saveCommandToHistory,
  loadCommandHistory,
} from "../utils/terminal/utils";

const Terminal = () => {
  const [currentPath, setCurrentPath] = useState("/");
  const [commandHistory, setCommandHistory] = useState<Command[]>([
    {
      input: "",
      output:
        'Welcome to Atridad\'s Shell!\nType "help" to see available commands.\n',
      timestamp: new Date(),
      path: "/",
    },
  ]);
  const [currentInput, setCurrentInput] = useState("");
  const [historyIndex, setHistoryIndex] = useState(-1);
  const [fileSystem, setFileSystem] = useState<{ [key: string]: any }>({});
  const [isTrainRunning, setIsTrainRunning] = useState(false);
  const [trainPosition, setTrainPosition] = useState(100);
  const [persistentHistory, setPersistentHistory] = useState<string[]>([]);
  const inputRef = useRef<HTMLInputElement>(null);
  const terminalRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (terminalRef.current && !isTrainRunning) {
      terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
    }
  }, [commandHistory, isTrainRunning]);

  // Load command history from localStorage
  useEffect(() => {
    const history = loadCommandHistory();
    setPersistentHistory(history);
  }, []);

  // Initialize file system
  useEffect(() => {
    buildFileSystem().then(setFileSystem);
  }, []);

  const handleSubmit = (e: JSX.TargetedEvent<HTMLFormElement>) => {
    e.preventDefault();

    const commandContext: CommandContext = {
      currentPath,
      fileSystem,
      setCurrentPath,
      setIsTrainRunning,
      setTrainPosition,
    };

    const output = executeCommand(currentInput, commandContext);
    const newCommand: Command = {
      input: currentInput,
      output,
      timestamp: new Date(),
      path: currentPath,
    };

    // Save command to persistent history
    const updatedHistory = saveCommandToHistory(
      currentInput,
      persistentHistory,
    );
    setPersistentHistory(updatedHistory);

    if (currentInput.trim().toLowerCase() === "clear") {
      setCommandHistory([]);
    } else {
      setCommandHistory((prev: Command[]) => [...prev, newCommand]);
    }

    setCurrentInput("");
    setHistoryIndex(-1);
  };

  const handleKeyDown = (e: JSX.TargetedKeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Tab") {
      e.preventDefault();

      const { completion, replaceFrom } = getCompletions(
        currentInput,
        currentPath,
        fileSystem,
      );

      if (completion) {
        const beforeReplacement = currentInput.substring(0, replaceFrom);
        const newInput = beforeReplacement + completion;
        setCurrentInput(newInput + (completion.endsWith("/") ? "" : " "));
      }
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      if (persistentHistory.length > 0) {
        const newIndex =
          historyIndex === -1
            ? persistentHistory.length - 1
            : Math.max(0, historyIndex - 1);
        setHistoryIndex(newIndex);
        setCurrentInput(persistentHistory[newIndex]);
      }
    } else if (e.key === "ArrowDown") {
      e.preventDefault();
      if (historyIndex !== -1) {
        const newIndex = Math.min(
          persistentHistory.length - 1,
          historyIndex + 1,
        );
        if (
          newIndex === persistentHistory.length - 1 &&
          historyIndex === newIndex
        ) {
          setHistoryIndex(-1);
          setCurrentInput("");
        } else {
          setHistoryIndex(newIndex);
          setCurrentInput(persistentHistory[newIndex]);
        }
      }
    }
  };

  return (
    <div className="bg-base-100 text-base-content font-mono text-sm h-full flex flex-col rounded-lg border-2 border-primary shadow-2xl relative">
      <div className="bg-base-200 px-4 py-2 rounded-t-lg border-b border-base-300">
        <div className="flex items-center space-x-2">
          <div className="w-3 h-3 bg-error rounded-full"></div>
          <div className="w-3 h-3 bg-warning rounded-full"></div>
          <div className="w-3 h-3 bg-success rounded-full"></div>
          <span className="ml-4 text-base-content/70 text-xs">
            guest@atri.dad: {currentPath}
          </span>
        </div>
      </div>

      <div
        ref={terminalRef}
        className={`flex-1 p-4 overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-base-100 relative ${
          isTrainRunning ? "opacity-0" : "opacity-100"
        }`}
        onClick={() => !isTrainRunning && inputRef.current?.focus()}
      >
        <div className="min-h-full">
          {commandHistory.map((command: Command, index: number) => (
            <div key={index} className="mb-2">
              {command.input && (
                <div className="flex items-center">
                  <span className="text-primary font-semibold">
                    guest@atri.dad
                  </span>
                  <span className="text-base-content">:</span>
                  <span className="text-secondary font-semibold">
                    {command.path}
                  </span>
                  <span className="text-base-content">$ </span>
                  <span className="text-accent">{command.input}</span>
                </div>
              )}
              {command.output && (
                <div
                  className="whitespace-pre-wrap text-base-content/80 mt-1"
                  dangerouslySetInnerHTML={{
                    __html: formatOutput(command.output),
                  }}
                />
              )}
            </div>
          ))}

          {!isTrainRunning && (
            <form onSubmit={handleSubmit} className="flex items-center">
              <span className="text-primary font-semibold">guest@atri.dad</span>
              <span className="text-base-content">:</span>
              <span className="text-secondary font-semibold">
                {currentPath}
              </span>
              <span className="text-base-content">$ </span>
              <input
                ref={inputRef}
                type="text"
                value={currentInput}
                onInput={(e) =>
                  setCurrentInput((e.target as HTMLInputElement).value)
                }
                onKeyDown={handleKeyDown}
                className="flex-1 bg-transparent border-none outline-none text-accent ml-1"
                spellcheck={false}
              />
            </form>
          )}
        </div>
      </div>

      {/* Train animation overlay - positioned over the content area but outside the opacity div */}
      {isTrainRunning && (
        <div className="absolute inset-x-0 top-16 bottom-0 flex items-center justify-center overflow-hidden pointer-events-none">
          <div
            className="text-white font-mono text-xs whitespace-nowrap"
            style={{
              transform: `translateX(${trainPosition}%)`,
              transition: "none",
            }}
          >
            <pre className="leading-none">{`
      ====        ________                ___________
  _D _|  |_______/        \\__I_I_____===__|_________|
   |(_)---  |   H\\________/ |   |        =|___ ___|      _________________
   /     |  |   H  |  |     |   |         ||_| |_||     _|                \\_____A
  |      |  |   H  |__--------------------| [___] |   =|                        |
  | ________|___H__/__|_____/[][]~\\_______|       |   -|                        |
  |/ |   |-----------I_____I [][] []  D   |=======|____|________________________|_
__/ =| o |=-O=====O=====O=====O \\ ____Y___________|__|__________________________|_
 |/-=|___|=    ||    ||    ||    |_____/~\\___/          |_D__D__D_|  |_D__D__D_|
  \\_/      \\__/  \\__/  \\__/  \\__/      \\_/               \\_/   \\_/    \\_/   \\_/`}</pre>
          </div>
        </div>
      )}
    </div>
  );
};

export default Terminal;
