// API response block — dark code surface with syntax highlighting + typing animation.

const apiStyles = {
  wrap: {
    width: "100%",
    maxWidth: 460,
    background: "var(--code-bg)",
    border: "1px solid rgba(255, 255, 255, 0.06)",
    borderRadius: 18,
    padding: "20px 22px 22px",
    fontFamily: '"JetBrains Mono", ui-monospace, monospace',
    color: "#E9E4F2",
    boxShadow: "0 24px 48px -28px rgba(70, 59, 94, 0.35)",
    position: "relative",
    overflow: "hidden",
  },
  bgGlow: {
    position: "absolute",
    top: -80,
    right: -80,
    width: 200,
    height: 200,
    background:
      "radial-gradient(closest-side, rgba(196, 168, 232, 0.18), transparent)",
    pointerEvents: "none",
  },
  header: {
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    marginBottom: 14,
    fontFamily: '"DM Sans", sans-serif',
  },
  label: {
    fontSize: 10.5,
    letterSpacing: 1.6,
    fontWeight: 600,
    color: "rgba(233, 228, 242, 0.55)",
    textTransform: "uppercase",
  },
  endpoint: {
    fontSize: 11,
    color: "rgba(233, 228, 242, 0.45)",
    fontFamily: '"JetBrains Mono", monospace',
    display: "flex",
    alignItems: "center",
    gap: 8,
  },
  methodPill: {
    fontSize: 9.5,
    letterSpacing: 0.6,
    fontWeight: 600,
    padding: "2px 6px",
    borderRadius: 4,
    background: "rgba(120, 200, 160, 0.18)",
    color: "#8DDDB1",
  },
  pre: {
    margin: 0,
    fontSize: 13,
    lineHeight: 1.65,
    whiteSpace: "pre",
    fontFamily: '"JetBrains Mono", monospace',
    color: "#CFC8DD",
  },
  cursor: {
    display: "inline-block",
    width: 7,
    height: 14,
    background: "#C4A8E8",
    marginLeft: 1,
    verticalAlign: "-2px",
    animation: "lc-blink 1s steps(2, start) infinite",
  },
};

// Color tokens for syntax
const SYNTAX = {
  key: "#9DB7E0",          // soft blue-lavender for keys
  string: "#A7CDE8",       // blue strings
  stringVerified: "#8DDDB1", // green for "verified"
  literalTrue: "#8DDDB1",
  literalFalse: "#E58A93",
  literalNull: "#C4A8E8",
  number: "#F4C8A0",
  punct: "rgba(207, 200, 221, 0.55)",
};

function colorizeValue(key, value) {
  if (value === null) return { color: SYNTAX.literalNull, text: "null" };
  if (value === true) return { color: SYNTAX.literalTrue, text: "true" };
  if (value === false) return { color: SYNTAX.literalFalse, text: "false" };
  if (typeof value === "number") return { color: SYNTAX.number, text: String(value) };
  if (typeof value === "string") {
    const isStatus = key === "status";
    const isVerified = isStatus && value === "verified";
    const isFailed = isStatus && (value === "rejected" || value === "expired");
    return {
      color: isVerified ? SYNTAX.stringVerified
        : isFailed ? SYNTAX.literalFalse
        : SYNTAX.string,
      text: `"${value}"`,
    };
  }
  return { color: SYNTAX.string, text: JSON.stringify(value) };
}

// Build the JSON as an array of typed segments so we can animate typing
function buildSegments(api) {
  const entries = Object.entries(api);
  const segs = [];
  segs.push({ text: "{\n", color: SYNTAX.punct });
  entries.forEach(([k, v], i) => {
    segs.push({ text: "  ", color: SYNTAX.punct });
    segs.push({ text: `"${k}"`, color: SYNTAX.key });
    segs.push({ text: ": ", color: SYNTAX.punct });
    const cv = colorizeValue(k, v);
    segs.push({ text: cv.text, color: cv.color });
    segs.push({
      text: i < entries.length - 1 ? ",\n" : "\n",
      color: SYNTAX.punct,
    });
  });
  segs.push({ text: "}", color: SYNTAX.punct });
  return segs;
}

function ApiBlock({ api, animateKey, play = true, onDone }) {
  const segments = React.useMemo(() => buildSegments(api), [api]);
  const totalLen = segments.reduce((n, s) => n + s.text.length, 0);
  const [count, setCount] = React.useState(totalLen);

  React.useEffect(() => {
    if (!play) {
      setCount(totalLen);
      return;
    }
    setCount(0);
    let i = 0;
    let cancelled = false;
    const baseMs = 40;
    const linePauseMs = 340;

    const joinedText = segments.map((s) => s.text).join("");
    const tick = () => {
      if (cancelled) return;
      if (i >= totalLen) return;

      i = Math.min(totalLen, i + 1);
      setCount(i);

      const isNewline = joinedText[i - 1] === "\n";
      const delay = baseMs + (isNewline ? linePauseMs : 0);
      setTimeout(tick, delay);
    };

    setTimeout(tick, baseMs);

    return () => { cancelled = true; };
  }, [animateKey, totalLen, segments, play]);

  const doneRef = React.useRef(false);
  React.useEffect(() => {
    doneRef.current = false;
  }, [animateKey]);
  React.useEffect(() => {
    if (!onDone) return;
    if (!play) return;
    if (doneRef.current) return;
    if (count >= totalLen) {
      doneRef.current = true;
      onDone();
    }
  }, [count, totalLen, onDone]);

  // Render segments up to `count` characters
  let remaining = count;
  const rendered = [];
  for (const seg of segments) {
    if (remaining <= 0) break;
    const take = Math.min(seg.text.length, remaining);
    rendered.push(
      <span key={rendered.length} style={{ color: seg.color }}>
        {seg.text.slice(0, take)}
      </span>
    );
    remaining -= take;
  }

  return (
    <div style={apiStyles.wrap}>
      <div style={apiStyles.bgGlow} />
      <div style={apiStyles.header}>
        <span style={apiStyles.label}>API Response</span>
        <span style={apiStyles.endpoint}>
          <span style={apiStyles.methodPill}>POST</span>
          /v1/verify
        </span>
      </div>
      <pre style={apiStyles.pre}>
        {rendered}
        {play && count < totalLen && <span style={apiStyles.cursor} />}
      </pre>
    </div>
  );
}

window.ApiBlock = ApiBlock;
