// Calculator card — pool count + rarity label + recalc strip + filter list
// + nested squares. Widths along the headline column are reserved so toggling
// filters never reflows the layout.

const PCT_MIN_WIDTH = 220;
const RARITY_LABEL_MIN_WIDTH = 130;
const POOL_EYEBROW_MIN_WIDTH = 220;

function Calculator({ active, toggle, pool }) {
  const [openFilter, setOpenFilter] = React.useState(null);
  const pct = (pool / window.BASE_POP) * 100;

  return (
    <div style={{ position: "relative", minWidth: 0 }}>
      <div
        style={{
          fontFamily: "var(--font-mono)",
          fontSize: 9.5,
          letterSpacing: "0.18em",
          opacity: 0.5,
          display: "flex",
          justifyContent: "flex-end",
          marginBottom: 8,
        }}
      >
        <span>
          TOGGLE FILTERS · CLICK{" "}
          <span style={{ color: "var(--accent)" }}>?</span> FOR SOURCES
        </span>
      </div>

      <div
        style={{
          border: "1px solid rgba(var(--fg-rgb), 0.13)",
          borderRadius: 3,
          padding: "var(--space-5)",
          background: "transparent",
          position: "relative",
          overflow: "hidden",
        }}
      >
        {/* HEADER — equation pattern.
            Left side  = the inputs and the result:
                         eyebrow ("source pool") + big percentage.
            Right side = what the result means:
                         rarity verdict + raw-count equivalent.
            Both sides carry substantive content, so the eye reads "left =
            right" rather than "left content + stranded label on the right".
            Recalc strip sits beneath as a single-line audit trail. */}
        <div style={{ minWidth: 0 }}>
          <div
            style={{
              display: "grid",
              gridTemplateColumns: "var(--calc-header-cols)",
              columnGap: "clamp(24px, 4vw, 56px)",
              rowGap: "var(--space-5)",
              alignItems: "flex-start",
            }}
          >
            <div style={{ minWidth: 0 }}>
              <div
                style={{
                  fontFamily: "var(--font-mono)",
                  fontSize: 9,
                  letterSpacing: "0.2em",
                  opacity: 0.5,
                  marginBottom: 6,
                }}
              >
                POOL · 36.5M PROFESSIONAL DEVS
              </div>
              <window.SmoothNumber
                value={pct}
                format={window.formatPct}
                style={{
                  fontFamily: "var(--font-serif)",
                  fontSize: "var(--pool-size)",
                  lineHeight: 0.95,
                  fontWeight: 400,
                  letterSpacing: "-0.04em",
                  fontVariantNumeric: "tabular-nums",
                  color: "var(--accent)",
                  display: "block",
                  minWidth: PCT_MIN_WIDTH,
                }}
              />
            </div>
            <div
              style={{
                minWidth: 0,
                paddingTop: "var(--space-2)",
                display: "flex",
                flexDirection: "column",
                gap: "var(--space-3)",
              }}
            >
              <window.RarityLabel
                pool={pool}
                style={{
                  fontSize: 16,
                  letterSpacing: "0.22em",
                  display: "block",
                  minWidth: RARITY_LABEL_MIN_WIDTH,
                }}
              />
              <div
                style={{
                  fontSize: 12,
                  lineHeight: 1.4,
                  fontFamily: "var(--font-mono)",
                  letterSpacing: "0.04em",
                  color: "rgba(var(--fg-rgb), 0.6)",
                  fontVariantNumeric: "tabular-nums",
                }}
              >
                = <window.SmoothNumber value={pool} /> developers match the filters
              </div>
            </div>
          </div>

          <div style={{ marginTop: "var(--space-3)" }}>
            <RecalcStrip active={active} pool={pool} />
          </div>
        </div>

        {/* BODY — filters and squares share the row below the header.
            alignItems: center vertically aligns the squares chart with the
            middle of the filter list. */}
        <div
          style={{
            display: "grid",
            gridTemplateColumns: "var(--calc-cols)",
            gap: "var(--calc-gap)",
            alignItems: "center",
            marginTop: "var(--space-4)",
          }}
        >
          <div style={{ minWidth: 0 }}>
            {window.RARE_FILTERS.map((f, i) => (
              <window.FilterRow
                key={f.id}
                f={f}
                i={i}
                on={active[f.id]}
                onToggle={() => toggle(f.id)}
                onOpen={() =>
                  setOpenFilter(openFilter?.id === f.id ? null : f)
                }
                isOpen={openFilter?.id === f.id}
              />
            ))}
          </div>

          <div
            style={{
              paddingTop: 4,
              display: "flex",
              flexDirection: "column",
              // Centers the squares within the column. With the squares
              // capped at SQ_MAX_W and the column potentially wider (mobile
              // single-col), this keeps the chart visually centered when it
              // wraps to its own row.
              alignItems: "center",
              minWidth: 0,
            }}
          >
            <window.NestedSquares active={active} pool={pool} />
          </div>
        </div>

        {openFilter && (
          <window.InfoPanel
            filter={openFilter}
            onClose={() => setOpenFilter(null)}
            style={{
              top: 14,
              right: 14,
              bottom: 14,
              width: "56%",
              maxWidth: 440,
            }}
          />
        )}
      </div>

    </div>
  );
}

// Single-line typewriter strip: $ recalc 1 * .15 * .005 * ... → 0.0012% of devs
// Reserved at one line height so toggling never reflows the row.
function RecalcStrip({ active, pool }) {
  const [visible, setVisible] = React.useState(true);
  const [text, setText] = React.useState("");
  const triggerRef = React.useRef(0);
  const firstRef = React.useRef(true);

  const target = React.useMemo(() => {
    const chosen = window.RARE_FILTERS.filter((f) => active[f.id]);
    const mult = chosen.length
      ? chosen
          .map((f) => f.passRate.toString().replace(/^0\./, "."))
          .join(" * ")
      : "1";
    const pct = (pool / window.BASE_POP) * 100;
    return `$ recalc 1 * ${mult} → ${window.formatPct(pct)} of devs`;
  }, [active, pool]);

  React.useEffect(() => {
    triggerRef.current += 1;
    const id = triggerRef.current;
    setVisible(true);
    setText("");
    let i = 0;
    const tick = () => {
      if (id !== triggerRef.current) return;
      i++;
      setText(target.slice(0, i));
      if (i < target.length) setTimeout(tick, 10);
      else {
        const dwell = firstRef.current ? 2400 : 1600;
        firstRef.current = false;
        setTimeout(() => {
          if (id === triggerRef.current) setVisible(false);
        }, dwell);
      }
    };
    tick();
  }, [target]);

  // Split visually so the result side (after →) reads slightly louder
  // than the command side, even though they live on one line.
  const arrowIdx = text.indexOf("→");
  const before = arrowIdx >= 0 ? text.slice(0, arrowIdx) : text;
  const after = arrowIdx >= 0 ? text.slice(arrowIdx) : "";

  return (
    <div
      style={{
        fontFamily: "var(--font-mono)",
        fontSize: 9.5,
        letterSpacing: "0.01em",
        minHeight: 16,
        height: 16,
        lineHeight: "16px",
        opacity: visible ? 0.7 : 0.22,
        transition: "opacity 0.7s ease",
        whiteSpace: "nowrap",
        overflow: "hidden",
        textOverflow: "ellipsis",
      }}
    >
      <span style={{ color: "rgba(var(--fg-rgb), 0.55)" }}>{before}</span>
      <span style={{ color: "rgba(var(--fg-rgb), 0.9)" }}>{after}</span>
      {visible && (
        <span
          style={{
            opacity: 0.6,
            animation: "rareBlink 1s steps(2) infinite",
            marginLeft: 3,
            color: "rgba(var(--fg-rgb), 0.55)",
          }}
        >
          ▊
        </span>
      )}
    </div>
  );
}

window.Calculator = Calculator;
