// qubit-roster.jsx — the five butterflies as instrument channels beside the
// mini-circuit (design handoff 2026-07-14, "list" variant). Each row shows
// the butterfly's wing color and its LIVE reduced-state purity from the
// simulator timeline. The damaged butterfly switches to its FIDELITY value
// from the rupture onward, flickering during the rupture itself.
//
// Exposes: window.QubitRoster.

(() => {
  // One representative color per butterfly — colorALight of each palette in
  // src/butterflyColors.js (roseGarden, goldenSun, dreamscape, candySwirl,
  // softSpectrum; butterflies cycle palettes in index order). Keep in sync.
  const QB_COLORS = ["#f594ba", "#fad675", "#d69cba", "#6ed6e6", "#b39ef2"];

  /* eased percentage — drifts toward its target (cubic ease-out, 1300ms) */
  function EasedPct({ target }) {
    const [val, setVal] = React.useState(target);
    const fromRef = React.useRef(target);
    React.useEffect(() => {
      const from = fromRef.current, delta = target - from;
      if (Math.abs(delta) < 0.0005) return;
      let raf, start = null;
      const step = (ts) => {
        if (start === null) start = ts;
        const p = Math.min(1, (ts - start) / 1300);
        const e = 1 - Math.pow(1 - p, 3);
        const v = from + delta * e;
        setVal(v);
        fromRef.current = v;
        if (p < 1) raf = requestAnimationFrame(step);
      };
      raf = requestAnimationFrame(step);
      return () => cancelAnimationFrame(raf);
    }, [target]);
    return <span>{(val * 100).toFixed(1) + "%"}</span>;
  }

  /* soft butterfly glyph matching the artwork's blurred silhouette.
     `damage` mirrors the wing shader (shaders.js): desaturate up to 80%,
     dim to 40% at full damage. */
  function QbIcon({ color, damage }) {
    const style = { color };
    if (damage > 0.001) {
      style.filter = "blur(.4px) drop-shadow(0 0 4px currentColor)" +
        " saturate(" + (1 - 0.8 * damage).toFixed(3) + ")" +
        " brightness(" + (1 - 0.6 * damage).toFixed(3) + ")";
    }
    return (
      <svg className="qb__icon" viewBox="0 0 24 20" aria-hidden="true" style={style}>
        <g fill="currentColor">
          <ellipse cx="6.9" cy="9.4" rx="5.6" ry="5.2" />
          <ellipse cx="17.1" cy="9.4" rx="5.6" ry="5.2" />
          <ellipse cx="8.4" cy="15.3" rx="3.9" ry="3.1" />
          <ellipse cx="15.6" cy="15.3" rx="3.9" ry="3.1" />
        </g>
        <g fill="none" stroke="currentColor" strokeWidth="0.9" strokeLinecap="round">
          <path d="M11.6 5.4 C10.6 3.2, 9 1.9, 7.4 1.4" />
          <path d="M12.4 5.4 C13.4 3.2, 15 1.9, 16.6 1.4" />
        </g>
      </svg>
    );
  }

  /* rupture flicker, capped at 5s (not the whole Separation chapter) */
  const FLICKER_MS = 5000;

  /**
   * @param purities     per-qubit purity [0,1] from the current snapshot
   * @param damagedQubit index of the damaged butterfly (0–4)
   * @param fid          damaged qubit's fidelity readout, null before rupture
   * @param rupture      true during the rupture (damage applied, heal not started)
   * @param colors       live wing colors from the animation (fallback: QB_COLORS)
   */
  function QubitRoster({ purities, damagedQubit, fid, rupture, colors }) {
    const [flicker, setFlicker] = React.useState(false);
    React.useEffect(() => {
      if (!rupture) { setFlicker(false); return; }
      setFlicker(true);
      const t = setTimeout(() => setFlicker(false), FLICKER_MS);
      return () => clearTimeout(t);
    }, [rupture]);

    return (
      <div className="qroster">
        {QB_COLORS.map((fallback, q) => {
          const color = (colors && colors[q]) || fallback;
          const isFid = q === damagedQubit && fid != null;
          const v = Math.max(0, Math.min(1, isFid ? fid : (purities && purities[q] != null ? purities[q] : 1)));
          // Same fidelity → damage mapping as the main butterfly (0.5 → full)
          const damage = isFid ? Math.max(0, Math.min(1, 2 * (1 - v))) : 0;
          const cls = "qb" + (isFid ? " qb--fid" : "") + (isFid && flicker ? " qb--rupture" : "");
          return (
            <div key={q} className={cls} style={{ "--qb-color": color }}>
              <QbIcon color={color} damage={damage} />
              <div className="qb__col">
                <div className="qb__row">
                  <span className="qb__label">{"qubit " + (q + 1)}</span>
                  <span className="qb__val">
                    <EasedPct target={v} />
                    <span className="qb__unit">{isFid ? "fid" : "pur"}</span>
                  </span>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    );
  }

  window.QubitRoster = QubitRoster;
})();
