// Terminal.jsx — inline flowing input (not fixed at bottom), bigger fonts, VFS navigation

const termStyles = {
  wrapper: {
    flex: "1",
    minHeight: "180px",
    background: "#060606",
    display: "flex",
    flexDirection: "column",
    position: "relative",
    overflow: "hidden",
  },
  topStrip: {
    height: "22px",
    minHeight: "22px",
    background: "rgba(255,90,0,0.04)",
    borderBottom: "1px solid rgba(255,90,0,0.1)",
    display: "flex",
    alignItems: "center",
    padding: "0 12px",
    gap: "10px",
    flexShrink: 0,
  },
  topLabel: (color) => ({
    fontSize: "11px", letterSpacing: "0.22em",
    color: color || "#555", fontFamily: "'JetBrains Mono', monospace",
  }),
  // Single scrollable area containing ALL history + current input line
  scrollArea: {
    flex: "1",
    overflowY: "auto",
    padding: "8px 12px 10px 12px",
    display: "flex",
    flexDirection: "column",
    justifyContent: "flex-start",
  },
  line: {
    fontSize: "13px",
    lineHeight: "1.35",
    fontFamily: "'JetBrains Mono', 'Courier New', monospace",
    whiteSpace: "pre-wrap",
    wordBreak: "break-all",
    flexShrink: 0,
  },
  colors: {
    output:  "#888",
    error:   "#ff4444",
    success: "#00ff88",
    orange:  "#ff5a00",
    dim:     "#3a3a3a",
    white:   "#f0f0f0",
    green:   "#00cc66",
  },
  // Inline input line (last item inside scrollArea)
  inputLine: {
    display: "flex",
    alignItems: "center",
    flexShrink: 0,
    marginTop: "0px",
    position: "relative",
  },
  promptUser:   { color: "#00ff88", fontFamily: "'JetBrains Mono', monospace", fontSize: "13px" },
  promptAt:     { color: "#555",    fontFamily: "'JetBrains Mono', monospace", fontSize: "13px" },
  promptHost:   { color: "#ff5a00", fontFamily: "'JetBrains Mono', monospace", fontSize: "13px" },
  promptPath:   { color: "#999",    fontFamily: "'JetBrains Mono', monospace", fontSize: "13px" },
  promptDollar: { color: "#f0f0f0", fontFamily: "'JetBrains Mono', monospace", fontSize: "13px", marginRight: "7px" },
  inputText: {
    color: "#f0f0f0", fontFamily: "'JetBrains Mono', monospace",
    fontSize: "13px", whiteSpace: "pre",
  },
  blockCursor: {
    display: "inline-block", width: "0.58em", height: "1em",
    background: "#ff5a00", animation: "blink-cursor 0.75s step-end infinite",
    verticalAlign: "middle", marginLeft: "1px",
  },
  // Hidden real input overlays the entire inputLine div
  hiddenInput: {
    position: "absolute", opacity: 0, left: 0, top: 0,
    width: "100%", height: "100%", border: "none", outline: "none",
    background: "transparent", cursor: "text", zIndex: 10,
    fontFamily: "'JetBrains Mono', monospace", fontSize: "13px",
  },
};

const VFS = {
  root: {
    "about-me.md":   { type: "file",  section: "about" },
    "skills.md":     { type: "file",  section: "skills" },
    "experience.md": { type: "file",  section: "experience" },
    "projects":       { type: "dir" },
    "certifications": { type: "dir" },
    "contact":        { type: "dir" },
  },
  projects: {
    "buff-marketplace-monitor.md": { type: "file" },
    "devops-automation-tool.md": { type: "file" },
    "terminal-portfolio.md": { type: "file" },
  },
  contact: {
    "email.md": { type: "file" }, "github.md": { type: "file" },
    "linkedin.md": { type: "file" },
  },
  certifications: {
    "az-900.md": { type: "file" },
    "az-204.md": { type: "file" },
    "gh-300.md": { type: "file" },
  },
};
const CAT_FILES = { "about-me.md": "about", "skills.md": "skills", "experience.md": "experience" };

function PromptSpan({ path }) {
  return (
    <span style={{ display: "inline-flex", alignItems: "center" }}>
      <span style={termStyles.promptUser}>user</span>
      <span style={termStyles.promptAt}>@</span>
      <span style={termStyles.promptHost}>portfolio</span>
      <span style={termStyles.promptPath}>:{path}$</span>
      <span style={termStyles.promptDollar}>&nbsp;</span>
    </span>
  );
}

function Terminal({ onNavigate, currentDir, onSubFileOpen }) {
  const { useState, useEffect, useRef } = React;

  const getPath = (dir) => dir ? `~/${dir}` : "~";

  const [history, setHistory] = useState([
    { type: "orange", text: "PORTFOLIO TERMINAL v2.5 // SECURE CHANNEL" },
    { type: "dim",    text: "─────────────────────────────────────────" },
    { type: "output", text: "Type 'help' for available commands." },
  ]);

  const [input, setInput]     = useState("");
  const [cmdHist, setCmdHist] = useState([]);
  const [histIdx, setHistIdx] = useState(-1);
  const [focused, setFocused] = useState(true);

  const inputRef = useRef(null);
  const areaRef  = useRef(null);

  // Scroll to bottom whenever history changes (shows the input line)
  useEffect(() => {
    if (areaRef.current) areaRef.current.scrollTop = areaRef.current.scrollHeight;
  }, [history]);

  const processCommand = (raw) => {
    const trimmed = raw.trim();
    const path = getPath(currentDir);
    const promptEcho = { type: "prompt-echo", text: trimmed, path };

    if (!trimmed) { setHistory((h) => [...h, promptEcho]); return; }

    const parts = trimmed.split(/\s+/);
    const cmd   = parts[0].toLowerCase();
    const arg   = parts[1] || "";
    const { PORTFOLIO_DATA } = window;
    const currentFs = currentDir ? VFS[currentDir] : VFS.root;
    let output = [];

    switch (cmd) {
      case "help":
        output = PORTFOLIO_DATA.commands.help.map((t) => ({ type: "output", text: t }));
        break;

      case "ls": {
        if (arg && arg !== ".") {
          const target = currentFs[arg];
          if (!target) {
            output = [{ type: "error", text: `ls: cannot access '${arg}': No such file or directory` }];
            break;
          }
          if (target.type === "file") {
            output = [{ type: "output", text: arg }];
            break;
          }
          // If it's a directory, list its contents
          const subFs = VFS[arg];
          if (subFs) {
            output.push({ type: "dim", text: `${arg}/` });
            Object.entries(subFs).forEach(([name, node]) => {
              output.push(node.type === "dir"
                ? { type: "green", text: `  ${name}/` }
                : { type: "output", text: `  ${name}` });
            });
          } else {
            output = [{ type: "output", text: `${arg}/` }];
          }
          break;
        }
        output.push({ type: "dim", text: `${getPath(currentDir)}/` });
        Object.entries(currentFs).forEach(([name, node]) => {
          output.push(node.type === "dir"
            ? { type: "green",  text: `  ${name}/` }
            : { type: "output", text: `  ${name}` });
        });
        break;
      }

      case "pwd":
        output = [{ type: "output", text: `/home/user/portfolio${currentDir ? `/${currentDir}` : ""}` }];
        break;

      case "cd": {
        if (!arg) {
          output = [{ type: "error", text: "bash: cd: missing argument" }];
          break;
        }
        if (arg === "~" || arg === "/") {
          onNavigate(null, null);
          output = [];
          break;
        }
        if (arg === "..") {
          onNavigate(null, null);
          output = [];
          break;
        }
        const target = currentFs[arg];
        if (!target) {
          if (currentDir !== null && VFS.root[arg]) {
            output = [
              { type: "error",  text: `bash: cd: ${arg}: No such file or directory` },
              { type: "output", text: `hint: you are inside '${currentDir}/', use 'cd ..' first` },
            ];
          } else {
            output = [{ type: "error", text: `bash: cd: ${arg}: No such file or directory` }];
          }
          break;
        }
        if (target.type === "file") {
          output = [{ type: "error", text: `bash: cd: ${arg}: Not a directory` }];
          break;
        }
        if (currentDir !== null) {
          output = [
            { type: "error",  text: `bash: cd: ${arg}: No such file or directory` },
            { type: "output", text: `hint: use 'cd ..' to go back to root first` },
          ];
          break;
        }
        output = [{ type: "green", text: `Entering ${arg}/` }];
        onNavigate(arg, arg);
        break;
      }

      case "cat": {
        if (!arg) { output = [{ type: "error", text: "usage: cat <filename.txt>" }]; break; }
        const entry = currentFs[arg];
        if (!entry) {
          if (currentDir !== null && VFS.root[arg]) {
            output = [
              { type: "error",  text: `bash: cat: ${arg}: No such file or directory` },
              { type: "output", text: `hint: ${arg} is at root level, use 'cd ..' first` },
            ];
          } else {
            output = [{ type: "error", text: `bash: cat: ${arg}: No such file or directory` }];
          }
          break;
        }
        if (entry.type === "dir") {
          output = [{ type: "error", text: `bash: cat: ${arg}: Is a directory` }]; break;
        }
        const section = CAT_FILES[arg];
        if (section) {
          output = [{ type: "orange", text: `Reading ${arg}...` }];
          onNavigate(currentDir, section);
        } else if (currentDir && VFS[currentDir] && VFS[currentDir][arg]) {
          // File inside a subdirectory — open via onSubFileOpen (same as mouse click)
          const fileKeys = Object.keys(VFS[currentDir]);
          const idx = fileKeys.indexOf(arg);
          const dirType = currentDir === "contact" ? "contact" : currentDir === "certifications" ? "certificate" : "project";
          output = [{ type: "orange", text: `cat ${currentDir}/${arg}` }];
          if (onSubFileOpen) onSubFileOpen(idx, dirType);
        } else {
          output = [{ type: "error", text: `bash: cat: ${arg}: No such file or directory` }];
        }
        break;
      }

      case "whoami":
        output = PORTFOLIO_DATA.commands.whoami.map((t) => ({ type: "success", text: t }));
        break;
      case "status":
        output = PORTFOLIO_DATA.commands.status.map((t) => ({ type: "orange", text: t }));
        break;
      case "clear":
        setHistory([]);
        setCmdHist((h) => (raw.trim() ? [raw.trim(), ...h] : h));
        setInput(""); setHistIdx(-1);
        return;
      case "echo":
        output = [{ type: "output", text: parts.slice(1).join(" ") }];
        break;
      case "date":
        output = [{ type: "output", text: new Date().toUTCString() }];
        break;
      case "uname":
        output = [{ type: "output", text: "PORTFOLIO.SYS 2.5 hrishikeshghule.com React 18.3.1" }];
        break;
      default:
        output = [
          { type: "error",  text: `bash: ${cmd}: command not found` },
          { type: "output", text: "type 'help' for available commands" },
        ];
    }

    setHistory((h) => [...h, promptEcho, ...output]);
    if (raw.trim()) setCmdHist((h) => [raw.trim(), ...h]);
    
    // Audio feedback for command execution
    const hasError = output.some(o => o.type === "error");
    if (window.playTerminalSound) {
      window.playTerminalSound(hasError ? 'error' : 'enter');
    }

    setInput(""); setHistIdx(-1);
  };

  const handleInputChange = (e) => {
    const val = e.target.value;
    setInput(val);
    // Subtle typing tick (only 60% of the time to avoid being annoying)
    if (window.playTerminalSound && Math.random() < 0.6) {
      window.playTerminalSound('tick');
    }
  };

  const handleKeyDown = (e) => {
    if (e.key === "Enter") {
      processCommand(input);
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      const next = histIdx + 1;
      if (next < cmdHist.length) { setHistIdx(next); setInput(cmdHist[next]); }
    } else if (e.key === "ArrowDown") {
      e.preventDefault();
      const next = histIdx - 1;
      if (next < 0) { setHistIdx(-1); setInput(""); }
      else { setHistIdx(next); setInput(cmdHist[next]); }
    } else if (e.key === "Tab") {
      e.preventDefault();
      const cmds = ["help","ls","pwd","cd","cat","whoami","status","clear","echo"];
      const match = cmds.find((c) => c.startsWith(input) && c !== input);
      if (match) setInput(match);
    }
  };

  const lineColor = (type) => ({
    error: "#ff4444", success: "#00ff88", orange: "#ff5a00",
    green: "#00cc66", dim: "#3a3a3a", white: "#f0f0f0",
  }[type] || "#888");

  const promptPath = getPath(currentDir);

  const RandomCursor = ({ focused }) => {
    const [visible, setVisible] = useState(true);
    const [opacity, setOpacity] = useState(1);
    const [jitter, setJitter] = useState(0);

    useEffect(() => {
      if (!focused) return;
      let timeoutId;

      const tick = () => {
        const rand = Math.random();
        let nextDelay = Math.random() * 800 + 300;

        if (rand < 0.7) {
          // Normal blink
          setVisible(v => !v);
          setOpacity(1);
          setJitter(0);
        } else if (rand < 0.85) {
          // Rapid double flicker
          setVisible(false);
          setTimeout(() => setVisible(true), 50);
          setTimeout(() => setVisible(false), 100);
          setTimeout(() => setVisible(true), 150);
          nextDelay = 200;
        } else if (rand < 0.92) {
          // Pause (keep current state longer)
          nextDelay = Math.random() * 1500 + 500;
        } else if (rand < 0.97) {
          // Dim state
          setOpacity(0.4);
          setVisible(true);
        } else {
          // Subtle jitter
          setJitter(Math.random() > 0.5 ? 1 : -1);
          setTimeout(() => setJitter(0), 50);
        }

        timeoutId = setTimeout(tick, nextDelay);
      };

      timeoutId = setTimeout(tick, 500);
      return () => clearTimeout(timeoutId);
    }, [focused]);

    return (
      <span style={{
        ...termStyles.blockCursor,
        opacity: focused ? (visible ? opacity : 0) : 0,
        transform: `translateX(${jitter}px)`,
        animation: "none", // Override static animation
        transition: "opacity 0.05s"
      }} />
    );
  };

  return (
    <div style={termStyles.wrapper} onClick={() => inputRef.current?.focus()}>
      {/* Scrollable area: history + inline input */}
      <div style={termStyles.scrollArea} ref={areaRef}>
        {history.map((entry, i) => {
          if (entry.type === "prompt-echo") {
            return (
              <div key={i} style={{ ...termStyles.line, display: "flex", alignItems: "baseline" }}>
                <PromptSpan path={entry.path} />
                <span style={termStyles.inputText}>{entry.text}</span>
              </div>
            );
          }
          return (
            <div key={i} style={{ ...termStyles.line, color: lineColor(entry.type) }}>
              {entry.text || "\u00a0"}
            </div>
          );
        })}

        {/* ── Current input line — inline, flows right after last output ── */}
        <div style={termStyles.inputLine}>
          <PromptSpan path={promptPath} />
          <span style={termStyles.inputText}>{input}</span>
          <RandomCursor focused={focused} />
          {/* Hidden real input captures all keyboard events */}
          <input
            ref={inputRef}
            id="terminal-input"
            value={input}
            onChange={handleInputChange}
            onKeyDown={handleKeyDown}
            onFocus={() => setFocused(true)}
            onBlur={() => setFocused(false)}
            style={termStyles.hiddenInput}
            autoFocus
            autoComplete="off"
            autoCorrect="off"
            autoCapitalize="off"
            spellCheck="false"
            aria-label="Terminal input"
          />
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Terminal });
