// Persistent Terminal HUD — bottom of the screen.
// Lives in a portal-ish fixed container; accepts navigation commands.
// Diegetic: glowing monospace strip with breadcrumbs + a prompt.

const { useState, useEffect, useRef, useCallback } = React;

function Terminal({ route, onNavigate, history, onPushHistory }) {
  const [input, setInput] = useState("");
  const [open, setOpen] = useState(false);
  const [hint, setHint] = useState(null);
  const inputRef = useRef(null);
  const linesRef = useRef(null);

  // breadcrumb
  const crumbs = route.world === "home"
    ? ["~"]
    : route.detail
      ? ["~", route.world, route.detail]
      : ["~", route.world];

  const breadcrumb = crumbs.join(" / ");

  // open with `/`
  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "/" && document.activeElement.tagName !== "INPUT") {
        e.preventDefault();
        setOpen(true);
        setTimeout(() => inputRef.current?.focus(), 30);
      }
      if (e.key === "Escape") {
        setOpen(false);
        inputRef.current?.blur();
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  useEffect(() => {
    if (open && linesRef.current) {
      linesRef.current.scrollTop = linesRef.current.scrollHeight;
    }
  }, [open, history]);

  const runCommand = useCallback((raw) => {
    const cmd = raw.trim();
    if (!cmd) return;
    const push = (text, kind = "out") => onPushHistory({ cmd: null, text, kind });
    onPushHistory({ cmd, text: null });

    const [head, ...rest] = cmd.split(/\s+/);
    const arg = rest.join(" ").toLowerCase();

    switch (head.toLowerCase()) {
      case "help":
      case "?":
        push("commands:");
        push("  cd <projects|professional|creative|personal|home>   enter world");
        push("  open <leviathan|jarvis|easyapply|inquire>           open project plate");
        push("  play <a1|a2|b1|b2 | music|writing|commentary|live>   creative · liner notes");
        push("  zoom <origins|people|reading|habits|curiosities|convictions>   personal · branch");
        push("  back                                                 step out");
        push("  home                                                 return to Z-stack");
        push("  ls                                                   list current contents");
        push("  whoami                                               anchor copy");
        push("  contact                                              linkedin");
        push("  clear                                                clear scroll");
        break;
      case "cd": {
        const target = arg.replace(/^\//, "").replace(/^~$/, "home");
        const valid = ["projects", "professional", "creative", "personal", "home"];
        if (valid.includes(target)) {
          onNavigate(target === "home" ? { world: "home" } : { world: target });
        } else {
          push(`cd: no such world: ${target || "(empty)"}`, "err");
        }
        break;
      }
      case "open": {
        const known = ["leviathan", "jarvis", "easyapply", "inquire"];
        if (known.includes(arg)) {
          onNavigate({ world: "projects", detail: arg });
        } else {
          push(`open: unknown plate: ${arg}`, "err");
        }
        break;
      }
      case "play": {
        const alias = {
          a1: "a1", a2: "a2", b1: "b1", b2: "b2",
          music: "a1", writing: "a2", research: "a2", commentary: "b1", live: "b2",
          front: "front", back: "back",
        };
        const target = alias[arg];
        if (target) {
          onNavigate({ world: "creative", detail: target === "front" ? null : target });
        } else {
          push(`play: unknown track: ${arg}. try a1|a2|b1|b2 or music|writing|commentary|live.`, "err");
        }
        break;
      }
      case "zoom": {
        const known = ["origins", "people", "reading", "habits", "curiosities", "convictions"];
        if (known.includes(arg)) {
          onNavigate({ world: "personal", detail: arg });
        } else {
          push(`zoom: unknown branch: ${arg}. try ${known.join(" | ")}.`, "err");
        }
        break;
      }
      case "back":
        if (route.detail) onNavigate({ world: route.world });
        else if (route.world !== "home") onNavigate({ world: "home" });
        else push("back: already at root", "err");
        break;
      case "home":
        onNavigate({ world: "home" });
        break;
      case "ls":
        if (route.world === "home") {
          push("projects/        professional/        creative/        personal/");
        } else if (route.world === "projects" && !route.detail) {
          push("leviathan.plate   jarvis.plate   easyapply.plate   inquire.plate");
        } else if (route.world === "professional") {
          push("timeline.spine   (11 nodes)");
        } else if (route.world === "creative" && !route.detail) {
          push("front.cover   back.cover   a1.music   a2.writing   b1.commentary   b2.live");
        } else if (route.world === "creative") {
          push(`now reading: liner notes for ${route.detail}`);
        } else if (route.world === "personal" && !route.detail) {
          push("branches/  01.origins  02.people  03.reading  04.habits  05.curiosities  06.convictions");
        } else if (route.world === "personal") {
          push(`zoomed: ${route.detail}.branch`);
        }
        break;
      case "whoami":
        push(`${ABOUT.name} — ${ABOUT.tagline}`);
        push(ABOUT.bio);
        break;
      case "contact":
        push(`linkedin → ${ABOUT.linkedin}`);
        break;
      case "clear":
        onPushHistory("__clear");
        break;
      default:
        push(`${head}: command not found. try \`help\`.`, "err");
    }
  }, [onNavigate, onPushHistory, route]);

  const onSubmit = (e) => {
    e.preventDefault();
    runCommand(input);
    setInput("");
  };

  // suggestion hint
  useEffect(() => {
    if (!input) { setHint(null); return; }
    const words = [
      "help", "ls", "cd projects", "cd professional", "cd creative", "cd personal",
      "open leviathan", "open jarvis", "open easyapply", "open inquire",
      "play music", "play writing", "play commentary", "play live", "play back", "play front",
      "play a1", "play a2", "play b1", "play b2",
      "zoom origins", "zoom people", "zoom reading", "zoom habits", "zoom curiosities", "zoom convictions",
      "back", "home", "whoami", "contact", "clear"
    ];
    const m = words.find((w) => w.startsWith(input.toLowerCase()) && w !== input.toLowerCase());
    setHint(m ? m.slice(input.length) : null);
  }, [input]);

  return (
    <div style={termStyles.root}>
      {/* expanded console */}
      {open && (
        <div style={termStyles.console}>
          <div style={termStyles.consoleHeader}>
            <span style={{ color: "var(--amber)" }}>● </span>
            <span style={{ color: "var(--fg-2)" }}>arihant@portfolio</span>
            <span style={{ color: "var(--muted)" }}> : </span>
            <span style={{ color: "var(--phosphor)" }}>{breadcrumb}</span>
            <span style={{ flex: 1 }}></span>
            <span style={{ color: "var(--muted)", fontSize: 10, letterSpacing: ".18em" }}>ESC TO CLOSE</span>
          </div>
          <div ref={linesRef} style={termStyles.consoleBody} className="scroller">
            {history.map((h, i) => (
              <div key={i} style={termStyles.line}>
                {h.cmd != null ? (
                  <>
                    <span style={{ color: "var(--amber)" }}>›</span>
                    <span style={{ color: "var(--fg)", marginLeft: 8 }}>{h.cmd}</span>
                  </>
                ) : (
                  <span style={{
                    color: h.kind === "err" ? "var(--rust)" : "var(--fg-2)",
                    paddingLeft: 14,
                    whiteSpace: "pre-wrap",
                  }}>{h.text}</span>
                )}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* always-on prompt strip */}
      <TickerTape />
      <div style={termStyles.strip}>
        <div style={termStyles.crumb}>
          <span style={{ color: "var(--amber)" }}>●</span>
          <span style={{ color: "var(--muted)" }}>arihant@portfolio</span>
          <span style={{ color: "var(--dim)" }}>:</span>
          <span style={{ color: "var(--phosphor)" }}>{breadcrumb}</span>
        </div>

        <form onSubmit={onSubmit} style={termStyles.form}>
          <span style={{ color: "var(--amber)" }}>›</span>
          <div style={{ position: "relative", flex: 1 }}>
            <input
              ref={inputRef}
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onFocus={() => setOpen(true)}
              placeholder="type `help`, or `cd projects` — press / to focus"
              style={termStyles.input}
              spellCheck={false}
              autoCapitalize="off"
              autoCorrect="off"
            />
            {hint && (
              <span style={termStyles.hint}>
                <span style={{ opacity: 0 }}>{input}</span>
                <span>{hint}</span>
              </span>
            )}
          </div>
          <span style={termStyles.kbd}>↵</span>
        </form>

        <div style={termStyles.right}>
          <span style={{ color: "var(--dim)" }}>{nowStamp()}</span>
          <span style={{ color: "var(--line-2)" }}>│</span>
          <span style={{ color: "var(--muted)" }}>v1.0.0</span>
        </div>
      </div>
    </div>
  );
}

function nowStamp() {
  const d = new Date();
  const p = (n) => String(n).padStart(2, "0");
  return `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
}

const termStyles = {
  root: {
    position: "fixed",
    left: 0, right: 0, bottom: 0,
    zIndex: 60,
    fontFamily: "var(--mono)",
    fontSize: 12,
    pointerEvents: "none",
  },
  console: {
    pointerEvents: "auto",
    margin: "0 16px",
    background: "oklch(10% 0.012 60 / 0.92)",
    backdropFilter: "blur(12px) saturate(120%)",
    WebkitBackdropFilter: "blur(12px) saturate(120%)",
    border: "1px solid var(--line)",
    borderBottom: "none",
    boxShadow: "0 -10px 40px oklch(0% 0 0 / 0.5)",
    maxHeight: 240,
    display: "flex",
    flexDirection: "column",
  },
  consoleHeader: {
    display: "flex",
    alignItems: "center",
    padding: "8px 14px",
    borderBottom: "1px dashed var(--line)",
    color: "var(--fg-2)",
    fontSize: 11,
  },
  consoleBody: {
    overflowY: "auto",
    padding: "10px 14px",
    flex: 1,
  },
  line: { lineHeight: 1.6, fontSize: 12 },

  strip: {
    pointerEvents: "auto",
    display: "grid",
    gridTemplateColumns: "auto 1fr auto",
    alignItems: "center",
    gap: 16,
    padding: "10px 18px",
    margin: "0 16px 16px",
    background: "oklch(10% 0.012 60 / 0.88)",
    backdropFilter: "blur(10px) saturate(120%)",
    WebkitBackdropFilter: "blur(10px) saturate(120%)",
    border: "1px solid var(--line)",
    boxShadow:
      "0 8px 30px oklch(0% 0 0 / 0.55), inset 0 0 0 1px oklch(100% 0 0 / 0.02), 0 0 60px oklch(80% 0.14 70 / 0.06)",
  },
  crumb: { display: "flex", alignItems: "center", gap: 8, whiteSpace: "nowrap" },
  form: {
    display: "flex", alignItems: "center", gap: 10,
    background: "oklch(7% 0.01 60 / 0.6)",
    border: "1px solid var(--line)",
    padding: "8px 12px",
  },
  input: {
    background: "transparent",
    border: 0,
    outline: 0,
    color: "var(--fg)",
    fontFamily: "var(--mono)",
    fontSize: 13,
    width: "100%",
    caretColor: "var(--amber)",
    position: "relative",
    zIndex: 1,
  },
  hint: {
    position: "absolute",
    top: 0, left: 0,
    pointerEvents: "none",
    color: "var(--dim)",
    fontFamily: "var(--mono)",
    fontSize: 13,
    whiteSpace: "pre",
  },
  kbd: {
    color: "var(--muted)",
    fontSize: 10,
    border: "1px solid var(--line)",
    padding: "1px 6px",
  },
  right: { display: "flex", gap: 10, alignItems: "center", whiteSpace: "nowrap" },
};

window.Terminal = Terminal;
