// zdr-beam.jsx — "Zero Data Retention" hero animation.
// A document of context fades in beside Wisbid, travels along the rail to the
// model provider and fades out (sent, nothing kept). A response then fades in
// beside the provider and returns to Wisbid before fading out. The document
// stays in the corridor between the two icons and never overlaps them.
// Clean, minimal, looping, reduced-motion aware. Exports window.ZdrBeam.
//
// React hooks (useState/useEffect/useRef) and Icon are already global,
// destructured upstream in landing-mockups.jsx.

(function () {
  const M = window.Motion || {};
  const motion = M.motion;
  const ease = [0.16, 1, 0.3, 1];
  const moveEase = [0.4, 0, 0.2, 1];

  const useZdrT = () => {
    const i18n = (typeof window !== "undefined" && window.Wisbid && window.Wisbid.i18n) || null;
    const [, force] = useState(0);
    useEffect(() => {
      if (!i18n) return;
      return i18n.subscribe(() => force((v) => v + 1));
    }, [i18n]);
    return (k, fb) => i18n ? i18n.t(k, fb) : fb;
  };

  const DOC_W = 38, DOC_H = 46;
  const ICON_HALF = 22;   // half of .zb-ico
  const GAP = 12;          // clearance between icon and document

  const ZdrBeam = () => {
    const t = useZdrT();
    const [geo, setGeo] = useState(null);     // { startX, endX, y }
    const [docX, setDocX] = useState(0);
    const [docOp, setDocOp] = useState(0);
    const [tint, setTint] = useState("ctx");   // ctx | ans

    const laneRef = useRef(null);
    const wIcoRef = useRef(null);
    const pIcoRef = useRef(null);

    useEffect(() => {
      const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
      // Positions are measured relative to the lane, so the document rides the
      // dashed rail and sits beside (never on top of) the two icons.
      const center = (ref) => {
        const s = laneRef.current, e = ref.current;
        if (!s || !e) return null;
        const sr = s.getBoundingClientRect(), r = e.getBoundingClientRect();
        return { x: r.left - sr.left + r.width / 2, y: r.top - sr.top + r.height / 2 };
      };

      const timers = [];
      const at = (fn, ms) => timers.push(setTimeout(fn, ms));

      const start = () => {
        const wc = center(wIcoRef), pc = center(pIcoRef);
        if (!wc || !pc || pc.x <= wc.x) { at(start, 120); return; } // retry until laid out
        // anchor (top-left) positions: just right of Wisbid, just left of provider
        const startX = wc.x + ICON_HALF + GAP;            // doc left edge clears the icon
        const endX = pc.x - ICON_HALF - GAP - DOC_W;
        const y = wc.y - DOC_H / 2;                        // centred on the rail
        setGeo({ startX, endX, y });
        setDocX(startX);

        if (reduced) { setDocOp(1); return; }

        const run = () => {
          setTint("ctx"); setDocX(startX); setDocOp(0);
          let e = 420;
          at(() => setDocOp(1), e);                 // context fades in beside Wisbid
          e += 540;
          at(() => setDocX(endX), e);               // travels to the provider
          e += 1080;
          at(() => setDocOp(0), e);                 // fades out at the provider
          e += 460;
          at(() => { setTint("ans"); setDocOp(1); }, e);  // response fades in beside provider
          e += 540;
          at(() => setDocX(startX), e);             // returns toward Wisbid
          e += 1080;
          at(() => setDocOp(0), e);                 // fades out beside Wisbid
          e += 760;                                  // idle beat
          at(run, e);
        };
        run();
      };
      at(start, 60);
      return () => { timers.forEach(clearTimeout); };
    }, []);

    return (
      <div className="zb-wrap">
        <div className="zb-card">
          <div className="zb-stage">
            <div className="zb-scene">
              <div className="zb-lane" ref={laneRef}>
                <div className="zb-rail" aria-hidden="true" />

                <div className="zb-node">
                  <span className="zb-ico" ref={wIcoRef}>
                    <img src="assets/wisbid-icon.svg" alt="" />
                  </span>
                  <span className="zb-node-label">{t("zdr.node.wisbid", "Wisbid")}</span>
                </div>

                <div className="zb-node">
                  <span className="zb-ico" ref={pIcoRef}>
                    <Icon name="box" size={21} />
                  </span>
                  <span className="zb-node-label">{t("zdr.node.provider", "Model provider")}</span>
                  <span className="zb-store">
                    <Icon name="lock" size={10} />
                    {t("zdr.store.done", "Nothing retained")}
                  </span>
                </div>

                {/* travelling document */}
                {motion && geo && (
                  <motion.div
                    className={`zb-doc ${tint === "ans" ? "is-ans" : ""}`}
                    initial={false}
                    animate={{ x: docX, opacity: docOp, scale: docOp ? 1 : 0.94 }}
                    transition={{
                      x: { duration: 1.0, ease: moveEase },
                      opacity: { duration: 0.42, ease },
                      scale: { duration: 0.42, ease },
                    }}
                    style={{ position: "absolute", top: geo.y, left: 0 }}>
                    <div className="zb-doc-card">
                      <div className="zb-doc-line w1" />
                      <div className="zb-doc-line w2" />
                      <div className="zb-doc-line w3" />
                    </div>
                  </motion.div>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  };

  window.ZdrBeam = ZdrBeam;
})();
