/* global React */
/* =====================================================================
   LOCKED WORLD components — ransom note, decrypt animation, game-over
   ===================================================================== */

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

// --------- shared ASCII art (skull) ---------
const SKULL_ASCII = String.raw`
       ▄▄▄▄▄▄▄▄▄▄
     ▄█▀▀░░░░░░░▀▀█▄
    █▀░░▄▄▄▄░▄▄▄▄░░▀█
   █░░░██▀▀██░██▀▀██░░█
   █░░░██▄▄██░██▄▄██░░█
   █░░░░░░░░░░░░░░░░░░█
   █░░░░░░▄▄▄▄▄▄░░░░░░█
    █▄░░░▀▀▀▀▀▀░░░░▄█
     ▀█▄░░░░░░░░░▄█▀
       ▀▀█████▀▀
`;

const BREACH_BANNER = String.raw`
 ██████╗ ██████╗ ███████╗ █████╗  ██████╗██╗  ██╗
 ██╔══██╗██╔══██╗██╔════╝██╔══██╗██╔════╝██║  ██║
 ██████╔╝██████╔╝█████╗  ███████║██║     ███████║
 ██╔══██╗██╔══██╗██╔══╝  ██╔══██║██║     ██╔══██║
 ██████╔╝██║  ██║███████╗██║  ██║╚██████╗██║  ██║
 ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝ ╚═════╝╚═╝  ╚═╝
            C  O  L  L  E  C  T  I  V  E
`;

// --------- LockedScreen ----------------------------------------------
function LockedScreen({ timer, onCorrectKey, decryptKey, tweaks }) {
  const [value, setValue] = useState("");
  const [shake, setShake] = useState(false);
  const [mockMsg, setMockMsg] = useState(null);
  const inputRef = useRef(null);
  const [now, setNow] = useState(Date.now());

  // re-render once a second so timer ticks
  useEffect(() => {
    const id = setInterval(() => setNow(Date.now()), 250);
    return () => clearInterval(id);
  }, []);

  useEffect(() => {
    // autofocus the input
    setTimeout(() => inputRef.current?.focus(), 100);
  }, []);

  const remaining = Math.max(0, timer.endsAt - now);
  const mins = Math.floor(remaining / 60000);
  const secs = Math.floor((remaining % 60000) / 1000);
  const timerClass =
    remaining < 60000 ? "crit" :
    remaining < 5 * 60000 ? "warn" :
    "";

  const mockingMessages = [
    "Really? \"" + (value || "") + "\"? You thought that would work?",
    "Wrong. Try again. Tick-tock, genius.",
    "Nope. Maybe ask whoever's password got us in here.",
    "Incorrect. We're laughing, you know.",
    "Pathetic guess. The clock's still moving.",
    "Wrong key. Want a hint? No? Good. We weren't going to give one.",
    "That's a no. Try thinking like the person whose credentials we stole.",
    "Denied. Your IT team is somewhere crying right now.",
  ];

  function submit(e) {
    e?.preventDefault();
    if (!value.trim()) return;
    const guess = value.trim();

    if (guess.toLowerCase() === decryptKey.toLowerCase()) {
      onCorrectKey();
      return;
    }

    // wrong
    setShake(true);
    setTimeout(() => setShake(false), 500);
    const msg = mockingMessages[Math.floor(Math.random() * mockingMessages.length)];
    setMockMsg({ text: msg, id: Date.now() });
  }

  return (
    <div className="locked-world">
      <div className="rw-shell">
        <div className="rw-topbar">
          <div><span className="dot"></span>SYSTEM COMPROMISED · BREACH-2026-A47</div>
          <div>NODE: HTI-MAIL-01 · STATUS: LOCKED</div>
        </div>

        <pre className="rw-asciibox">{BREACH_BANNER}</pre>

        <div className="rw-subhead">⚠ All your files have been encrypted ⚠</div>

        <h1 className="rw-headline">
          You've Been <span className="accent">Owned.</span>
        </h1>

        <div className="rw-body" style={{ marginTop: 24 }}>
          <p>
            This device and every system attached to it — mail servers, shared drives,
            cloud backups, that one Dropbox account you forgot about — is no longer
            under your control. Your files are encrypted with military-grade nonsense
            you don't want to understand.
          </p>
          <p>
            Don't bother calling your IT team. They're the reason we're here.
          </p>
          <p style={{ marginTop: 16 }}>
            But we're not monsters. We're <strong>educators</strong>.
            And today's lesson? <em>Accountability.</em>
          </p>
        </div>

        <hr className="rw-section-rule" />

        <div className="rw-body">
          <p>
            We gained access through <strong>one</strong> set of compromised credentials.
            Just one person's mistake. Your job is to figure out:
          </p>
        </div>

        <div className="rw-question-grid">
          <div className="rw-qcard">
            <div className="label">Question 01</div>
            <div className="value">WHO</div>
          </div>
          <div className="rw-qcard">
            <div className="label">Question 02</div>
            <div className="value">HOW</div>
          </div>
          <div className="rw-qcard">
            <div className="label">Question 03</div>
            <div className="value">WHERE</div>
          </div>
        </div>

        <div className="rw-body">
          <p>
            Get it right, and we'll trade you the decryption key.
            Get it wrong… and you'll never see your precious quarterly reports again.
          </p>
        </div>

        <div className="rw-timer-block">
          <div>
            <div className="rw-timer-label">Time remaining</div>
            <div className={"rw-timer-digits " + timerClass}>
              {String(mins).padStart(2, "0")}:{String(secs).padStart(2, "0")}
            </div>
          </div>
          <div className="rw-timer-meta">
            <div>// auto-wipe scheduled at T-00:00</div>
            <div>// no extensions</div>
            <div>// no negotiations</div>
          </div>
        </div>

        <div className="rw-body">
          <p>
            <strong>☎ Call us when you have the answers we want.</strong>{" "}
            You'll find our number. We hope.
          </p>
        </div>

        <form className="rw-key-form" onSubmit={submit}>
          <div className="prompt">
            ❯ Enter Decryption Key_
          </div>
          <div className="rw-key-input-row">
            <input
              ref={inputRef}
              className={"rw-key-input" + (shake ? " shake" : "")}
              value={value}
              onChange={(e) => setValue(e.target.value)}
              placeholder="••••••••••••••"
              autoComplete="off"
              spellCheck="false"
            />
            <button type="submit" className="rw-decrypt-btn">DECRYPT →</button>
          </div>

          {mockMsg && (
            <div className="rw-mock-msg" key={mockMsg.id}>
              {mockMsg.text}
              <span className="author">— The Breach Collective</span>
            </div>
          )}
        </form>

        <div className="rw-signoff">
          <div><span className="tag">SIGNED</span> The Breach Collective</div>
          <div style={{ marginTop: 12, color: "#888", fontSize: 12 }}>
            // tick · tock · tick · tock
          </div>
        </div>
      </div>
    </div>
  );
}

// --------- DecryptSequence -------------------------------------------
function DecryptSequence({ onComplete }) {
  const [lines, setLines] = useState([]);
  const [progress, setProgress] = useState(0);
  const [done, setDone] = useState(false);

  const fileList = useMemo(() => ([
    { name: "hr_records.xlsx", size: "4.2 MB" },
    { name: "client_database.sql", size: "812 MB" },
    { name: "Q4_financials.pdf", size: "1.1 MB" },
    { name: "exec_payroll.csv", size: "284 KB" },
    { name: "server_creds.kdbx", size: "12 KB" },
    { name: "engineering/source_code.zip", size: "1.4 GB" },
    { name: "marketing/campaigns_2026/", size: "—" },
    { name: "legal/contracts_signed/", size: "—" },
    { name: "personal_photos_dave.zip", size: "847 MB" },
    { name: ".ssh/id_rsa", size: "3 KB" },
    { name: "backup_jul_2026.tar.gz", size: "12.6 GB" },
    { name: "ALL_PASSWORDS_FINAL.txt", size: "29 KB" },
  ]), []);

  useEffect(() => {
    let cancelled = false;
    let lineIdx = 0;
    let progressVal = 0;

    const steps = [
      { delay: 400, line: { type: "ok", text: "› KEY VERIFIED. Decryption authorised." } },
      { delay: 300, line: { type: "info", text: "› Initialising AES-256-GCM reverse routine..." } },
      { delay: 300, line: { type: "info", text: "› Mounting encrypted volumes: //hti-prod/*" } },
      { delay: 300, line: { type: "info", text: "› Streaming decryption keys..." } },
      { delay: 300, line: { type: "spacer" } },
    ];

    async function run() {
      for (const s of steps) {
        await wait(s.delay);
        if (cancelled) return;
        setLines(prev => [...prev, { ...s.line, id: lineIdx++ }]);
      }

      // file decryption lines
      for (let i = 0; i < fileList.length; i++) {
        await wait(180 + Math.random() * 280);
        if (cancelled) return;
        const f = fileList[i];
        setLines(prev => [...prev, {
          type: "file",
          file: f.name,
          size: f.size,
          status: "OK",
          id: lineIdx++,
        }]);
        progressVal = Math.min(98, Math.round(((i + 1) / fileList.length) * 100));
        setProgress(progressVal);
      }

      await wait(400);
      if (cancelled) return;
      setLines(prev => [...prev,
        { type: "spacer", id: lineIdx++ },
        { type: "ok", text: "› All clusters restored. Integrity check: PASS", id: lineIdx++ },
        { type: "ok", text: "› Rebuilding DNS routes... done.", id: lineIdx++ },
        { type: "ok", text: "› Cleaning up Breach Collective payload... done.", id: lineIdx++ },
      ]);
      setProgress(100);

      await wait(700);
      if (cancelled) return;
      setDone(true);

      await wait(1400);
      if (cancelled) return;
      onComplete();
    }

    run();
    return () => { cancelled = true; };
    // eslint-disable-next-line
  }, []);

  return (
    <div className="decrypt-shell">
      <div className="decrypt-inner">
        <pre className="decrypt-banner">{`
 ██████╗ ███████╗ ██████╗██████╗ ██╗   ██╗██████╗ ████████╗
 ██╔══██╗██╔════╝██╔════╝██╔══██╗╚██╗ ██╔╝██╔══██╗╚══██╔══╝
 ██║  ██║█████╗  ██║     ██████╔╝ ╚████╔╝ ██████╔╝   ██║
 ██║  ██║██╔══╝  ██║     ██╔══██╗  ╚██╔╝  ██╔═══╝    ██║
 ██████╔╝███████╗╚██████╗██║  ██║   ██║   ██║        ██║
 ╚═════╝ ╚══════╝ ╚═════╝╚═╝  ╚═╝   ╚═╝   ╚═╝        ╚═╝
`}</pre>

        {lines.map((l) => {
          if (l.type === "spacer") return <div key={l.id} style={{ height: 8 }} />;
          if (l.type === "file") {
            return (
              <div key={l.id} className="decrypt-line">
                <span className="prompt">›</span>
                <span className="file">decrypting {l.file}</span>
                <span style={{ color: "#888" }}>{l.size}</span>
                <span className="status ok">[{l.status}]</span>
              </div>
            );
          }
          return (
            <div key={l.id} className="decrypt-line">
              <span style={{ color: l.type === "ok" ? "#34ff5e" : "#b8ffd0" }}>
                {l.text}
              </span>
            </div>
          );
        })}

        <div className="decrypt-bar">
          <span style={{ color: "#34ff5e" }}>PROGRESS</span>
          <div className="track">
            <div className="fill" style={{ "--p": progress }}></div>
          </div>
          <span className="pct">{progress}%</span>
        </div>

        {done && (
          <div className="decrypt-done">
            ╔════════════════════════════════════════╗<br />
            ║  ALL SYSTEMS RESTORED — REDIRECTING... ║<br />
            ╚════════════════════════════════════════╝
            <span className="decrypt-cursor"></span>
          </div>
        )}
      </div>
    </div>
  );
}

function wait(ms) { return new Promise(r => setTimeout(r, ms)); }

// --------- GameOver --------------------------------------------------
function GameOverScreen({ onRetry }) {
  return (
    <div className="gameover-shell">
      <div className="gameover-card">
        <pre className="ascii">{SKULL_ASCII}</pre>
        <h1>TIME'S UP.</h1>
        <p>
          The deadline passed. Your files have been auto-wiped, exfiltrated,
          and seeded across seventeen different file-sharing forums.
        </p>
        <p style={{ marginTop: 16, color: "#ff5050" }}>
          You should probably tell your CEO.
        </p>
        <div className="signoff">
          — The Breach Collective
        </div>
        <button
          onClick={onRetry}
          style={{
            marginTop: 32,
            padding: "12px 24px",
            border: "1px solid #ff2a2a",
            color: "#ff2a2a",
            fontFamily: "JetBrains Mono, monospace",
            fontSize: 13,
            letterSpacing: "0.2em",
            textTransform: "uppercase",
            background: "transparent",
          }}
        >
          Restart Scenario
        </button>
      </div>
    </div>
  );
}

// expose to global
Object.assign(window, { LockedScreen, DecryptSequence, GameOverScreen });
