// terminal.jsx — typing-effect terminal component
// Renders a sequence of "scenes" (cmd + output blocks) with realistic typing.

const { useState, useEffect, useRef } = React;

// A scene = { prompt, cmd, output: [{text, cls, delay?}] }
// Renders prompt, types `cmd` char-by-char, then streams output lines.

function Prompt({ host = 'm1tjtnrx', user = 'root', path = '~' }) {
  return (
    <span className="term-prompt">
      <span className="hash">┌──(</span>
      <span className="user">{user}</span>
      <span className="at">㉿</span>
      <span className="host">{host}</span>
      <span className="hash">)-[</span>
      <span className="path">{path}</span>
      <span className="hash">]</span>
      <br />
      <span className="hash">└─#</span>
      {' '}
    </span>
  );
}

function colorize(text) {
  // Color first token (command), then flags (-x, --xxx), then quoted args.
  // Returns array of React elements.
  const parts = [];
  const tokens = text.split(/(\s+)/);
  let firstWord = true;
  tokens.forEach((tok, i) => {
    if (/^\s+$/.test(tok)) { parts.push(tok); return; }
    if (firstWord) {
      parts.push(<span key={i} className="term-cmd">{tok}</span>);
      firstWord = false;
      return;
    }
    if (/^-/.test(tok)) {
      parts.push(<span key={i} className="term-flag">{tok}</span>);
    } else if (/^[A-Z]/.test(tok) || /^\d/.test(tok) || /\//.test(tok) || /\./.test(tok)) {
      parts.push(<span key={i} className="term-arg">{tok}</span>);
    } else {
      parts.push(tok);
    }
  });
  return parts;
}

function TerminalScene({ scene, speed = 18, onDone, reset }) {
  // Three phases: typing the command, then rendering outputs progressively,
  // then "done" (signals parent to advance to next scene).
  const [typed, setTyped] = useState('');
  const [outIdx, setOutIdx] = useState(0);
  const [phase, setPhase] = useState('typing');
  const timerRef = useRef(null);

  useEffect(() => {
    setTyped('');
    setOutIdx(0);
    setPhase('typing');
  }, [reset]);

  // Typing phase
  useEffect(() => {
    if (phase !== 'typing') return;
    const cmd = scene.cmd || '';
    if (typed.length >= cmd.length) {
      // small pause after typing
      timerRef.current = setTimeout(() => setPhase('outputting'), 280);
      return () => clearTimeout(timerRef.current);
    }
    // jittered speed for realism
    const jitter = speed + Math.random() * 35;
    timerRef.current = setTimeout(() => {
      setTyped(cmd.slice(0, typed.length + 1));
    }, jitter);
    return () => clearTimeout(timerRef.current);
  }, [phase, typed, scene.cmd, speed]);

  // Output phase
  useEffect(() => {
    if (phase !== 'outputting') return;
    const out = scene.output || [];
    if (outIdx >= out.length) {
      timerRef.current = setTimeout(() => {
        setPhase('done');
        if (onDone) onDone();
      }, 1400);
      return () => clearTimeout(timerRef.current);
    }
    const line = out[outIdx];
    const delay = line.delay ?? (line.text === '' ? 60 : 120 + Math.random() * 80);
    timerRef.current = setTimeout(() => {
      setOutIdx((i) => i + 1);
    }, delay);
    return () => clearTimeout(timerRef.current);
  }, [phase, outIdx, scene.output, onDone]);

  const visibleOutput = (scene.output || []).slice(0, outIdx);

  return (
    <>
      <div className="term-line">
        <Prompt host={scene.host || 'm1tjtnrx'} user={scene.user || 'root'} path={scene.path || '~'} />
        {colorize(typed)}
        {phase === 'typing' && <span className="term-caret" />}
      </div>
      {visibleOutput.map((line, i) => (
        <div key={i} className={`term-line ${line.cls || 'term-out'}`}>
          {line.text || '\u00A0'}
        </div>
      ))}
      {phase === 'outputting' && outIdx >= (scene.output || []).length && (
        <div className="term-line"><span className="term-caret" /></div>
      )}
    </>
  );
}

function Terminal({ scenes, title = 'Terminal', tabs = null, activeTab = null, onTabChange }) {
  const [sceneIdx, setSceneIdx] = useState(0);
  const [resetKey, setResetKey] = useState(0);
  const scrollRef = useRef(null);

  // Reset when tab changes
  useEffect(() => {
    setSceneIdx(0);
    setResetKey((k) => k + 1);
  }, [activeTab]);

  // When a scene finishes, advance (loop forever).
  const handleDone = () => {
    setTimeout(() => {
      setSceneIdx((i) => (i + 1) % scenes.length);
      setResetKey((k) => k + 1);
    }, 1200);
  };

  // Auto-scroll to bottom as output grows
  useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  });

  const current = scenes[sceneIdx];

  return (
    <div className="terminal">
      <div className="terminal-bar">
        <div className="dots">
          <span className="dot r" />
          <span className="dot y" />
          <span className="dot g" />
        </div>
        <span className="title">{title}</span>
        {tabs && (
          <div className="tabs">
            {tabs.map((t) => (
              <button
                key={t.id}
                className={`tab ${activeTab === t.id ? 'on' : ''}`}
                onClick={() => onTabChange && onTabChange(t.id)}
              >
                {t.label}
              </button>
            ))}
          </div>
        )}
      </div>
      <div className="terminal-body" ref={scrollRef}>
        <TerminalScene scene={current} reset={resetKey} onDone={handleDone} />
      </div>
    </div>
  );
}

window.Terminal = Terminal;
window.TerminalScene = TerminalScene;
window.Prompt = Prompt;
