// shared.jsx — Lupus constellation geometry (lifted from the user's banner.svg) + helpers
// Exports to window: LupusConstellation, Starfield, LUPUS_STARS, LUPUS_LINES

const LUPUS_STARS = [
  { x: 279, y: 234, r: 4.5, name: "α" },
  { x: 270, y: 182, r: 4.0, name: "β" },
  { x: 190, y: 143, r: 4.0, name: "γ" },
  { x: 228, y: 145, r: 3.5, name: "δ" },
  { x: 208, y: 190, r: 3.0, name: "ε" },
  { x: 223, y: 290, r: 3.5, name: "ζ" },
  { x: 120, y: 115, r: 3.0, name: "η" },
  { x: 197, y: 55,  r: 2.5, name: "φ" },
  { x: 134, y: 30,  r: 2.5, name: "χ" },
  { x: 317, y: 224, r: 2.0, name: "" },
  { x: 244, y: 231, r: 2.0, name: "" },
];

const LUPUS_LINES = [
  [[120,115],[134,30]], [[134,30],[197,55]], [[197,55],[120,115]],
  [[120,115],[190,143]], [[190,143],[228,145]], [[228,145],[270,182]],
  [[190,143],[208,190]], [[208,190],[223,290]], [[120,115],[223,290]],
  [[223,290],[279,234]],
];

// Deterministic pseudo-random (mulberry32) so starfields are stable across renders
function seededRandom(seed) {
  let a = seed >>> 0;
  return function () {
    a |= 0; a = (a + 0x6D2B79F5) | 0;
    let t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

// LupusConstellation — the constellation as an SVG.
// props: size (width px), stroke, starColor, glowColor (null = no glow),
//        lineOpacity, twinkle (bool), labels (bool), labelColor, labelFont
function LupusConstellation({
  size = 320,
  stroke = "#3b82f6",
  strokeWidth = 1.1,
  lineOpacity = 0.6,
  starColor = "#e2e8f0",
  glowColor = null,
  twinkle = false,
  labels = false,
  labelColor = "#64748b",
  labelFont = "ui-monospace, 'SF Mono', Menlo, monospace",
  labelMap = {},
  style = {},
}) {
  const vb = "95 5 240 305"; // tight crop around the figure
  const aspect = 305 / 240;
  return (
    <svg
      viewBox={vb}
      width={size}
      height={Math.round(size * aspect)}
      style={{ display: "block", overflow: "visible", ...style }}
      aria-label="Constelação Lupus"
    >
      <g stroke={stroke} strokeWidth={strokeWidth} fill="none" opacity={lineOpacity}>
        {LUPUS_LINES.map(([[x1, y1], [x2, y2]], i) => (
          <line key={i} x1={x1} y1={y1} x2={x2} y2={y2}></line>
        ))}
      </g>
      {glowColor && LUPUS_STARS.filter(s => s.r >= 3).map((s, i) => (
        <circle key={"g" + i} cx={s.x} cy={s.y} r={s.r * 3.6} fill={glowColor} opacity="0.35">
          {twinkle && (
            <animate
              attributeName="opacity"
              values="0.2;0.45;0.2"
              dur={(3 + (i % 4)) + "s"}
              repeatCount="indefinite"
            ></animate>
          )}
        </circle>
      ))}
      <g fill={starColor}>
        {LUPUS_STARS.map((s, i) => (
          <circle key={i} cx={s.x} cy={s.y} r={s.r}>
            {twinkle && s.r >= 3 && (
              <animate
                attributeName="r"
                values={`${s.r};${s.r * 1.25};${s.r}`}
                dur={(4 + (i % 3)) + "s"}
                repeatCount="indefinite"
              ></animate>
            )}
          </circle>
        ))}
      </g>
      {labels && (
        <g fontFamily={labelFont} fontSize="11" fill={labelColor}>
          {LUPUS_STARS.filter(s => s.name).map((s, i) => {
            const extra = labelMap[s.name];
            return (
              <g key={i}>
                <text x={s.x + 10} y={s.y + 2}>{s.name}</text>
                {extra && (
                  <text x={s.x + 22} y={s.y + 2} fill={labelColor} opacity="0.75">{extra}</text>
                )}
              </g>
            );
          })}
        </g>
      )}
    </svg>
  );
}

// Starfield — absolutely-positioned field of faint dots. Parent must be position:relative.
function Starfield({ count = 70, color = "#334155", seed = 7, maxR = 1.1, opacity = 1, twinkle = false }) {
  const rand = seededRandom(seed);
  const dots = Array.from({ length: count }, (_, i) => ({
    x: rand() * 100,
    y: rand() * 100,
    r: 0.4 + rand() * (maxR - 0.4),
    d: 3 + rand() * 5,
    id: i,
  }));
  return (
    <svg
      width="100%"
      height="100%"
      style={{ position: "absolute", inset: 0, pointerEvents: "none", opacity }}
      preserveAspectRatio="none"
    >
      {dots.map(d => (
        <circle key={d.id} cx={d.x + "%"} cy={d.y + "%"} r={d.r} fill={color}>
          {twinkle && d.id % 3 === 0 && (
            <animate
              attributeName="opacity"
              values="1;0.3;1"
              dur={d.d + "s"}
              repeatCount="indefinite"
            ></animate>
          )}
        </circle>
      ))}
    </svg>
  );
}

Object.assign(window, { LupusConstellation, Starfield, LUPUS_STARS, LUPUS_LINES });

// useViewport — reactive breakpoint hook. Returns the current width plus
// `mobile` (< 560px) and `compact` (< 820px) flags used to switch layouts.
function useViewport() {
  const get = () => (typeof window !== "undefined" ? window.innerWidth : 1200);
  const [w, setW] = React.useState(get);
  React.useEffect(() => {
    let raf = null;
    const onResize = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        raf = null;
        setW(get());
      });
    };
    window.addEventListener("resize", onResize);
    return () => {
      window.removeEventListener("resize", onResize);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);
  return { w: w, mobile: w < 560, compact: w < 820 };
}

Object.assign(window, { useViewport });

