// "Human in the loop" — three-panel sequence showing an ESCALATE being
// routed to Slack and an approved override being written to the audit log.
// Panels activate sequentially on scroll via IntersectionObserver.
const { useState: useStateHL, useEffect: useEffectHL, useRef: useRefHL } = React;

function useInView(threshold = 0.35) {
  const ref = useRefHL(null);
  const [inView, setInView] = useStateHL(false);
  useEffectHL(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) setInView(true); },
      { threshold }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [threshold]);
  return [ref, inView];
}

// Panel 1: terminal-style policy decision, types itself in line by line.
function PanelIntercept({ active, onDone, approved }) {
  const lines = [
    ["agent", "release-bot"],
    ["tool", "deploy_to_production"],
    ["risk_score", "94 / 100"],
    ["policy", "high-risk-deployment"],
    ["decision", "→ ESCALATE"],
    ["routing", "→ #eng-approvals"],
    ["latency", "0.08ms"],
  ];
  const [visible, setVisible] = useStateHL(0);
  useEffectHL(() => {
    if (!active) return;
    let i = 0;
    const id = setInterval(() => {
      i++;
      setVisible(i);
      if (i >= lines.length) {
        clearInterval(id);
        setTimeout(() => onDone && onDone(), 200);
      }
    }, 180);
    return () => clearInterval(id);
  }, [active]);

  return (
    <div
      style={{
        border: "1px solid var(--line)",
        borderRadius: 8,
        background: "linear-gradient(180deg, rgba(10,10,12,0.95), rgba(5,5,6,0.95))",
        padding: "16px 18px 20px",
        position: "relative",
        minHeight: 280,
      }}
    >
      <div
        className="mono"
        style={{
          fontSize: 10,
          letterSpacing: "0.22em",
          color: "var(--amber)",
          textTransform: "uppercase",
          marginBottom: 14,
          display: "flex",
          justifyContent: "space-between",
          alignItems: "center",
        }}
      >
        <span>Aurek · Policy engine</span>
        <span
          style={{
            width: 8, height: 8, borderRadius: "50%",
            background: approved ? "oklch(0.80 0.14 145)" : "var(--amber)",
            boxShadow: approved
              ? "0 0 10px oklch(0.80 0.14 145 / 0.9)"
              : "0 0 10px oklch(0.82 0.14 75 / 0.9)",
            animation: "pulseDot2 1.4s infinite",
            transition: "background .4s, box-shadow .4s",
          }}
        />
      </div>
      <div className="mono" style={{ fontSize: 12.5, lineHeight: 2 }}>
        {lines.map(([k, v], i) => {
          if (i >= visible) return <div key={k} style={{ height: 24 }}>&nbsp;</div>;
          const isDecision = k === "decision";
          const isRouting = k === "routing";
          return (
            <div key={k} style={{ display: "grid", gridTemplateColumns: "110px 1fr", gap: 8 }}>
              <span style={{ color: "var(--text-faint)" }}>{k}:</span>
              <span
                style={{
                  color: isDecision
                    ? "var(--amber)"
                    : isRouting
                    ? "var(--text)"
                    : "var(--text)",
                  fontWeight: isDecision ? 600 : 400,
                }}
              >
                {v}
              </span>
            </div>
          );
        })}
      </div>
      <style>{`@keyframes pulseDot2 { 0%,100%{opacity:1} 50%{opacity:0.35} }`}</style>
    </div>
  );
}

// Animated arrow: dashed line drawing itself, with a small label above.
function ArrowConnector({ active, label, color = "var(--amber)" }) {
  return (
    <div style={{ position: "relative", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", minWidth: 90 }}>
      <div
        className="mono"
        style={{
          fontSize: 10,
          letterSpacing: "0.18em",
          color: "var(--text-faint)",
          textTransform: "uppercase",
          marginBottom: 10,
          opacity: active ? 1 : 0,
          transition: "opacity .6s",
          whiteSpace: "nowrap",
        }}
      >
        {label}
      </div>
      <svg width="90" height="14" viewBox="0 0 90 14" aria-hidden>
        <line
          x1="4" y1="7" x2="72" y2="7"
          stroke={color}
          strokeWidth="1.4"
          strokeDasharray="4 3"
          strokeDashoffset={active ? 0 : 80}
          style={{ transition: "stroke-dashoffset 1s ease", opacity: active ? 1 : 0.2 }}
        />
        <path
          d="M 72 2 L 82 7 L 72 12"
          fill="none"
          stroke={color}
          strokeWidth="1.4"
          strokeLinejoin="round"
          strokeLinecap="round"
          style={{ opacity: active ? 1 : 0.2, transition: "opacity .3s .9s" }}
        />
      </svg>
    </div>
  );
}

// Panel 2: Slack-like notification with Approve / Deny buttons.
function PanelSlack({ active, onApproved }) {
  const [state, setState] = useStateHL("idle"); // idle → pressing → approved
  useEffectHL(() => {
    if (!active) return;
    const t1 = setTimeout(() => setState("pressing"), 1500);
    const t2 = setTimeout(() => {
      setState("approved");
      onApproved && onApproved();
    }, 1900);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, [active]);

  const flashGreen = state === "approved";

  return (
    <div
      style={{
        borderRadius: 10,
        background: "#1a1d21",
        border: "1px solid " + (flashGreen ? "oklch(0.80 0.14 145 / 0.6)" : "rgba(255,255,255,0.08)"),
        padding: "14px 16px 16px",
        boxShadow: flashGreen
          ? "0 0 30px oklch(0.80 0.14 145 / 0.25)"
          : "0 10px 30px rgba(0,0,0,0.4)",
        transition: "box-shadow .4s, border-color .4s",
        minHeight: 280,
      }}
    >
      {/* Sender header */}
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 10 }}>
        <div
          style={{
            width: 32, height: 32, borderRadius: 6,
            background: "#0b0b0c",
            display: "flex", alignItems: "center", justifyContent: "center",
            border: "1px solid rgba(255,255,255,0.08)",
          }}
        >
          <svg width="14" height="14" viewBox="0 0 1 1">
            {[[0.5,0.12],[0.28,0.42],[0.72,0.42],[0.16,0.78],[0.84,0.78],[0.38,0.78],[0.62,0.78]].map(([x,y],i)=>(
              <circle key={i} cx={x} cy={y} r={0.08} fill="#f3f0ea"/>
            ))}
          </svg>
        </div>
        <div style={{ display: "flex", flexDirection: "column" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontWeight: 700, color: "#f3f0ea", fontSize: 14 }}>Aurek</span>
            <span style={{ fontSize: 10, padding: "1px 5px", background: "rgba(255,255,255,0.08)", color: "#a8a29a", borderRadius: 3, letterSpacing: "0.05em" }}>APP</span>
            <span style={{ fontSize: 11, color: "#6b6860" }}>14:22</span>
          </div>
          <div style={{ fontSize: 11, color: "#6b6860" }}>
            in <span style={{ color: "#8ab4f8" }}>#eng-approvals</span>
          </div>
        </div>
      </div>

      <div style={{ fontSize: 14, fontWeight: 600, color: "#f3f0ea", marginBottom: 10 }}>
        Action requires approval
      </div>
      <div
        className="mono"
        style={{
          background: "#0f1113",
          border: "1px solid rgba(255,255,255,0.06)",
          borderRadius: 6,
          padding: "10px 12px",
          fontSize: 12,
          lineHeight: 1.7,
          color: "#c9c5bd",
          whiteSpace: "pre",
          marginBottom: 12,
        }}
      >
{`Agent:      release-bot
Tool:       deploy_to_production
Risk score: 94 / 100
Reason:     Production deploy outside
            change window. Requires
            senior engineer sign-off.

Context:    Branch main → prod
            Triggered by: scheduled job
            Time:         14:22:08 UTC`}
      </div>

      <div style={{ display: "flex", gap: 8 }}>
        <button
          style={{
            flex: 1,
            textAlign: "left",
            padding: "9px 12px",
            fontSize: 13,
            background: state === "pressing" ? "#1f2a20" : "#232629",
            color: "#f3f0ea",
            border: "1px solid rgba(255,255,255,0.1)",
            borderLeft: "3px solid oklch(0.80 0.14 145)",
            borderRadius: 4,
            cursor: "pointer",
            transform: state === "pressing" ? "translateY(1px)" : "translateY(0)",
            transition: "transform .1s, background .2s",
            display: "flex",
            alignItems: "center",
            gap: 8,
          }}
        >
          {state === "approved" ? (
            <>
              <svg width="14" height="14" viewBox="0 0 14 14">
                <path d="M3 7 L6 10 L11 4" fill="none" stroke="oklch(0.80 0.14 145)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
              </svg>
              <span style={{ color: "oklch(0.80 0.14 145)" }}>Approved by sarah.chen</span>
            </>
          ) : (
            "Approve"
          )}
        </button>
        <button
          style={{
            flex: 1,
            textAlign: "left",
            padding: "9px 12px",
            fontSize: 13,
            background: "#232629",
            color: "#f3f0ea",
            border: "1px solid rgba(255,255,255,0.1)",
            borderLeft: "3px solid oklch(0.70 0.18 25)",
            borderRadius: 4,
            opacity: state === "approved" ? 0.4 : 1,
            transition: "opacity .3s",
          }}
        >
          Deny
        </button>
      </div>
    </div>
  );
}

// Panel 3: audit log rows with scrambling hash.
function ScrambleHash({ final, start }) {
  const [text, setText] = useStateHL("#----..----");
  useEffectHL(() => {
    if (!start) return;
    const chars = "0123456789abcdef";
    let i = 0;
    const id = setInterval(() => {
      i++;
      if (i > 18) {
        setText(final);
        clearInterval(id);
        return;
      }
      let s = "#";
      for (let k = 0; k < 4; k++) s += chars[Math.floor(Math.random() * chars.length)];
      s += "..";
      for (let k = 0; k < 4; k++) s += chars[Math.floor(Math.random() * chars.length)];
      setText(s);
    }, 55);
    return () => clearInterval(id);
  }, [start, final]);
  return <span style={{ color: "var(--amber)", textShadow: "0 0 8px var(--amber-glow)" }}>{text}</span>;
}

function PanelAudit({ active }) {
  const [rowTwo, setRowTwo] = useStateHL(false);
  useEffectHL(() => {
    if (!active) return;
    const t = setTimeout(() => setRowTwo(true), 500);
    return () => clearTimeout(t);
  }, [active]);

  return (
    <div
      style={{
        border: "1px solid var(--line)",
        borderRadius: 8,
        background: "linear-gradient(180deg, rgba(10,10,12,0.95), rgba(5,5,6,0.95))",
        padding: "16px 18px",
        minHeight: 280,
      }}
    >
      <div
        className="mono"
        style={{
          fontSize: 10,
          letterSpacing: "0.22em",
          color: "var(--text-faint)",
          textTransform: "uppercase",
          marginBottom: 14,
        }}
      >
        tamper-evident audit log
      </div>

      <div
        className="mono"
        style={{
          border: "1px solid var(--line)",
          borderRadius: 6,
          padding: "10px 12px",
          background: "rgba(14,14,16,0.7)",
          fontSize: 12,
          lineHeight: 1.7,
          marginBottom: 8,
          opacity: active ? 1 : 0,
          transform: active ? "translateY(0)" : "translateY(-6px)",
          transition: "all .4s",
        }}
      >
        <div style={{ display: "grid", gridTemplateColumns: "110px 90px 1fr", gap: 10 }}>
          <span style={{ color: "var(--text-faint)" }}>14:22:08.104</span>
          <span style={{ color: "var(--amber)", fontWeight: 600 }}>ESCALATE</span>
          <span style={{ color: "var(--text)" }}>release-bot → deploy_to_prod</span>
        </div>
        <div style={{ color: "var(--text-faint)", marginLeft: 120, fontSize: 11.5 }}>
          risk:94 · routed → #eng-approvals
        </div>
      </div>

      <div
        className="mono"
        style={{
          border: "1px solid " + (rowTwo ? "oklch(0.80 0.14 145 / 0.35)" : "var(--line)"),
          borderRadius: 6,
          padding: "10px 12px",
          background: "rgba(14,14,16,0.7)",
          fontSize: 12,
          lineHeight: 1.7,
          opacity: rowTwo ? 1 : 0,
          transform: rowTwo ? "translateY(0)" : "translateY(-6px)",
          transition: "all .5s",
        }}
      >
        <div style={{ display: "grid", gridTemplateColumns: "110px 90px 1fr", gap: 10 }}>
          <span style={{ color: "var(--text-faint)" }}>14:22:41.887</span>
          <span style={{ color: "oklch(0.80 0.14 145)", fontWeight: 600 }}>OVERRIDE</span>
          <span style={{ color: "var(--text)" }}>approved by: sarah.chen</span>
        </div>
        <div style={{ marginLeft: 120, fontSize: 11.5, display: "flex", alignItems: "center", gap: 6 }}>
          <span style={{ color: "var(--text-faint)" }}>hash:</span>
          <ScrambleHash final="#9f3a..c821" start={rowTwo} />
          <svg width="10" height="10" viewBox="0 0 10 10" style={{ marginLeft: 2 }}>
            <rect x="2" y="4.5" width="6" height="4" rx="0.7" fill="none" stroke="var(--amber)" strokeWidth="0.8"/>
            <path d="M3.3 4.5 V3.3 a1.7 1.7 0 0 1 3.4 0 V4.5" fill="none" stroke="var(--amber)" strokeWidth="0.8"/>
          </svg>
        </div>
        <div style={{ color: "var(--text-faint)", marginLeft: 120, fontSize: 11.5 }}>
          reason: "scheduled maintenance window confirmed, proceed"
        </div>
      </div>

      <div
        className="mono"
        style={{
          fontSize: 10,
          letterSpacing: "0.18em",
          color: "var(--text-faint)",
          textTransform: "uppercase",
          marginTop: 16,
          textAlign: "center",
          opacity: rowTwo ? 1 : 0,
          transition: "opacity .6s .3s",
        }}
      >
        Tamper-evident · Exportable · Auditor-ready
      </div>
    </div>
  );
}

function HumanInTheLoop() {
  const [ref, inView] = useInView(0.25);
  const [approved, setApproved] = useStateHL(false);
  const [interceptDone, setInterceptDone] = useStateHL(false);
  const [showSlack, setShowSlack] = useStateHL(false);
  const [arrow2, setArrow2] = useStateHL(false);
  const [showAudit, setShowAudit] = useStateHL(false);

  useEffectHL(() => {
    if (!inView) return;
    // Arrow 1 + Slack panel ~ after intercept typing done
    if (interceptDone) {
      const t = setTimeout(() => setShowSlack(true), 600);
      return () => clearTimeout(t);
    }
  }, [inView, interceptDone]);

  useEffectHL(() => {
    if (!approved) return;
    const t1 = setTimeout(() => setArrow2(true), 400);
    const t2 = setTimeout(() => setShowAudit(true), 1000);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, [approved]);

  return (
    <section
      id="human-in-the-loop"
      ref={ref}
      style={{
        padding: "120px 28px",
        borderBottom: "1px solid var(--line)",
        position: "relative",
        background: "#0a0a0a",
        overflow: "hidden",
      }}
    >
      <div
        aria-hidden
        style={{
          position: "absolute",
          inset: 0,
          background: "radial-gradient(ellipse 50% 50% at 38% 55%, oklch(0.82 0.14 75 / 0.05), transparent 70%)",
          pointerEvents: "none",
        }}
      />
      <div style={{ maxWidth: 1200, margin: "0 auto", position: "relative" }}>
        <div
          className="mono"
          style={{
            fontSize: 10,
            letterSpacing: "0.3em",
            color: "var(--text-faint)",
            textTransform: "uppercase",
            marginBottom: 16,
          }}
        >
          ▸ Human in the loop
        </div>
        <h2
          style={{
            fontSize: 48,
            margin: "0 0 16px",
            letterSpacing: "-0.02em",
            fontWeight: 600,
            lineHeight: 1.08,
          }}
        >
          When the stakes are too high<br />to automate.
        </h2>
        <p
          style={{
            fontSize: 16,
            color: "var(--text-dim)",
            maxWidth: 680,
            lineHeight: 1.65,
            margin: "0 0 60px",
          }}
        >
          Some actions shouldn't be decided by a policy file alone. Aurek routes
          them to a human, captures the decision, and writes it to the audit
          trail — immutably.
        </p>

        <div
          style={{
            display: "grid",
            gridTemplateColumns: "1fr auto 1fr auto 1fr",
            gap: 0,
            alignItems: "center",
          }}
        >
          <div style={{ opacity: inView ? 1 : 0, transition: "opacity .5s" }}>
            <PanelIntercept active={inView} onDone={() => setInterceptDone(true)} approved={approved} />
          </div>
          <ArrowConnector active={interceptDone} label="routed in 0.08ms" color="var(--amber)" />
          <div style={{ opacity: showSlack ? 1 : 0.15, transition: "opacity .5s" }}>
            <PanelSlack active={showSlack} onApproved={() => setApproved(true)} />
          </div>
          <ArrowConnector active={arrow2} label="override logged" color="oklch(0.80 0.14 145)" />
          <div style={{ opacity: showAudit ? 1 : 0.15, transition: "opacity .5s" }}>
            <PanelAudit active={showAudit} />
          </div>
        </div>

        <div
          className="mono"
          style={{
            fontSize: 11,
            letterSpacing: "0.18em",
            color: "var(--text-faint)",
            textTransform: "uppercase",
            textAlign: "center",
            marginTop: 60,
            paddingTop: 28,
            borderTop: "1px dashed var(--line)",
          }}
        >
          Average human response time in pilot:{" "}
          <span style={{ color: "var(--amber)" }}>4 min 12 sec</span>
          {" · "}
          Zero unreviewed escalations.
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { HumanInTheLoop });
