/* contact.jsx — constellation graph + channel list */

const { useState: useStateC, useEffect: useEffectC, useRef: useRefC } = React;

const CHANNELS = [
  { k: "Email", v: "ptw151125@kaist.ac.kr", copy: true },
  { k: "GitHub", v: "github.com/TaewoooPark", href: "https://github.com/TaewoooPark" },
  { k: "X / Twitter", v: "@theoverstrcture", href: "https://twitter.com/theoverstrcture" },
  { k: "Instagram", v: "@t.wo0_x", href: "https://instagram.com/t.wo0_x" },
  { k: "LinkedIn", v: "in/taewoo-park-427a05352", href: "https://linkedin.com/in/taewoo-park-427a05352" },
  { k: "HUSTLY ARCHIV", v: "@hustlyarchiv.kr", href: "https://instagram.com/hustlyarchiv.kr" },
  { k: "Affiliation", v: "KAIST · Daejeon, KR" },
];

function Constellation() {
  const ref = useRefC(null);
  const [mouse, setMouse] = useStateC({ x: 0.5, y: 0.5 });
  useEffectC(() => {
    const c = ref.current; if (!c) return;
    const ctx = c.getContext("2d");
    let raf, t = 0;
    const resize = () => {
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      const r = c.getBoundingClientRect();
      c.width = r.width * dpr; c.height = r.height * dpr; ctx.scale(dpr, dpr);
    };
    resize();
    window.addEventListener("resize", resize);

    const N = 32;
    const nodes = Array.from({ length: N }, () => ({
      x: Math.random(), y: Math.random(),
      vx: (Math.random() - 0.5) * 0.0006,
      vy: (Math.random() - 0.5) * 0.0006,
      label: ["GH", "X", "IG", "@", "✉", "in", "·"][Math.floor(Math.random() * 7)],
    }));

    const onMove = (e) => {
      const r = c.getBoundingClientRect();
      setMouse({ x: (e.clientX - r.left) / r.width, y: (e.clientY - r.top) / r.height });
    };
    c.addEventListener("mousemove", onMove);

    const tick = () => {
      t += 0.005;
      const r = c.getBoundingClientRect();
      ctx.clearRect(0, 0, r.width, r.height);

      nodes.forEach(n => {
        n.x += n.vx; n.y += n.vy;
        if (n.x < 0 || n.x > 1) n.vx *= -1;
        if (n.y < 0 || n.y > 1) n.vy *= -1;
      });

      const mx = mouse.x * r.width, my = mouse.y * r.height;
      const pts = nodes.map(n => ({ x: n.x * r.width, y: n.y * r.height, label: n.label }));

      // Edges within distance, plus to mouse
      ctx.strokeStyle = "rgba(10,10,10,0.25)";
      ctx.lineWidth = 0.6;
      for (let i = 0; i < pts.length; i++) {
        for (let j = i + 1; j < pts.length; j++) {
          const d = Math.hypot(pts[i].x - pts[j].x, pts[i].y - pts[j].y);
          if (d < 160) {
            ctx.globalAlpha = 1 - d / 160;
            ctx.beginPath();
            ctx.moveTo(pts[i].x, pts[i].y);
            ctx.lineTo(pts[j].x, pts[j].y);
            ctx.stroke();
          }
        }
      }
      ctx.globalAlpha = 1;

      // mouse edges
      ctx.strokeStyle = "var(--fg)";
      ctx.lineWidth = 0.8;
      pts.forEach(p => {
        const d = Math.hypot(p.x - mx, p.y - my);
        if (d < 220) {
          ctx.globalAlpha = 1 - d / 220;
          ctx.beginPath();
          ctx.moveTo(p.x, p.y);
          ctx.lineTo(mx, my);
          ctx.stroke();
        }
      });
      ctx.globalAlpha = 1;

      // nodes
      pts.forEach(p => {
        ctx.fillStyle = "var(--fg)";
        ctx.beginPath();
        ctx.arc(p.x, p.y, 3, 0, Math.PI * 2);
        ctx.fill();
      });

      // mouse node
      ctx.fillStyle = "var(--fg)";
      ctx.beginPath();
      ctx.arc(mx, my, 5, 0, Math.PI * 2);
      ctx.fill();
      ctx.strokeStyle = "var(--fg)";
      ctx.beginPath();
      ctx.arc(mx, my, 14, 0, Math.PI * 2);
      ctx.stroke();

      raf = requestAnimationFrame(tick);
    };
    tick();
    return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", resize); c.removeEventListener("mousemove", onMove); };
  }, [mouse.x, mouse.y]);
  return <canvas ref={ref} style={{ width: "100%", height: "100%", position: "absolute", inset: 0 }} />;
}

function RadialCard() {
  useLang();
  const [hovered, setHovered] = useStateC(null);
  const nodes = [
    { id: "email",     label: "ptw151125@kaist.ac.kr", x: 16, y: 22, action: "copy", value: "ptw151125@kaist.ac.kr" },
    { id: "x",         label: "X / Twitter",           x: 84, y: 22, action: "open", value: "https://twitter.com/theoverstrcture" },
    { id: "linkedin",  label: "LinkedIn",              x: 14, y: 78, action: "open", value: "https://linkedin.com/in/taewoo-park-427a05352" },
    { id: "hustly",    label: "HUSTLY ARCHIV",         x: 50, y: 92, action: "open", value: "https://instagram.com/hustlyarchiv.kr" },
    { id: "instagram", label: "Instagram",             x: 86, y: 78, action: "open", value: "https://instagram.com/t.wo0_x" },
  ];
  const cx = 50, cy = 54;
  const [copied, setCopied] = useStateC(false);
  const onActivate = (n) => {
    if (n.action === "copy") {
      navigator.clipboard?.writeText(n.value);
      setCopied(true);
      setTimeout(() => setCopied(false), 1800);
    } else {
      window.open(n.value, "_blank", "noopener");
    }
  };
  return (
    <div className="radial-card" style={{
      border: "1px solid var(--line)", position: "relative",
      padding: 24, minHeight: 460, height: "100%",
      display: "flex", flexDirection: "column",
    }}>
      <div className="micro" style={{ color: "var(--fg-muted)", display: "flex", justifyContent: "space-between" }}>
        <span>{t("Card · Channel graph")}</span>
        <span style={{ opacity: copied ? 1 : 0, transition: "opacity 200ms" }}>{t("✓ copied to clipboard")}</span>
      </div>
      <div style={{ position: "relative", flex: 1, marginTop: 16 }}>
        <svg viewBox="0 0 100 100" preserveAspectRatio="none"
          style={{ position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none" }}>
          {nodes.map(n => (
            <line key={n.id}
              x1={cx} y1={cy} x2={n.x} y2={n.y}
              stroke="var(--fg)"
              strokeOpacity={hovered == null ? 0.55 : (hovered === n.id ? 1 : 0.12)}
              vectorEffect="non-scaling-stroke"
              style={{ transition: "stroke-opacity 220ms" }}
            />
          ))}
        </svg>
        <div style={{
          position: "absolute", left: `${cx}%`, top: `${cy}%`,
          transform: "translate(-50%, -50%)",
          width: 14, height: 14, borderRadius: "50%", background: "var(--fg)",
        }} />
        {nodes.map(n => {
          const isHover = hovered === n.id;
          return (
            <button key={n.id}
              type="button"
              onMouseEnter={() => window.__hasHover && setHovered(n.id)}
              onMouseLeave={() => window.__hasHover && setHovered(null)}
              onClick={() => onActivate(n)}
              data-cursor="link"
              data-cursor-label={n.action === "copy" ? t("Copy") : t("Open")}
              style={{
                position: "absolute", left: `${n.x}%`, top: `${n.y}%`,
                transform: "translate(-50%, -50%)",
                width: 140, height: 56,
                background: "transparent", border: "none", padding: 0,
                cursor: "none",
                zIndex: 2,
              }}>
              {/* Dot — centered on (n.x, n.y) */}
              <span style={{
                position: "absolute", left: "50%", top: "50%",
                transform: `translate(-50%, -50%) scale(${isHover ? 1.5 : 1})`,
                width: 12, height: 12, borderRadius: "50%",
                border: "1px solid var(--fg)",
                background: isHover ? "var(--fg)" : "var(--bg)",
                transition: "transform 200ms, background 200ms",
              }} />
              {/* Label — above the dot, still inside hit area */}
              <span className="radial-label" style={{
                position: "absolute", left: "50%", top: "50%",
                transform: "translate(-50%, calc(-50% - 18px))",
                whiteSpace: "nowrap",
                fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.04em",
                color: isHover ? "var(--fg)" : "var(--fg-muted)",
                fontStyle: isHover ? "italic" : "normal",
                transition: "color 200ms",
              }}>{t(n.label)}</span>
            </button>
          );
        })}
      </div>
      <div className="micro" style={{ color: "var(--fg-muted)", marginTop: 16 }}>
        {t("hover a node — click to copy or open")}
      </div>
    </div>
  );
}

function ChannelRow({ c }) {
  useLang();
  const [hover, setHover] = useStateC(false);
  const [copied, setCopied] = useStateC(false);
  const isOpen = !!c.href;
  const isCopy = !!c.copy;
  const isStatic = !isOpen && !isCopy;
  const onClick = () => {
    if (isCopy) {
      navigator.clipboard?.writeText(c.v);
      setCopied(true);
      setTimeout(() => setCopied(false), 2200);
    } else if (isOpen) {
      window.open(c.href, "_blank", "noopener,noreferrer");
    }
  };
  return (
    <button onClick={isStatic ? undefined : onClick}
      onMouseEnter={() => window.__hasHover && setHover(true)} onMouseLeave={() => window.__hasHover && setHover(false)}
      data-cursor={isStatic ? undefined : "link"}
      data-cursor-label={isStatic ? undefined : (isCopy ? t("Copy") : t("Open"))}
      className="channel-row"
      style={{
        display: "grid", gridTemplateColumns: "180px 1fr 30px",
        alignItems: "center", gap: 24,
        padding: "22px 0", borderTop: "1px solid var(--line-soft)",
        textAlign: "left", width: "100%", position: "relative",
        background: "transparent", border: "none",
        cursor: isStatic ? "default" : "none",
      }}>
      <span className="micro channel-k">{t(c.k)}</span>
      <span className="channel-v" style={{
        fontFamily: "var(--font-display)", fontSize: 28,
        position: "relative", height: 36, overflow: "hidden", display: "block",
      }}>
        <span style={{ display: "block", transform: hover && !isStatic ? "translateY(-100%)" : "translateY(0)", transition: "transform 320ms var(--easing-default)" }}>
          {copied ? t("✓ copied to clipboard") : t(c.v)}
        </span>
        <span style={{ display: "block", transform: hover && !isStatic ? "translateY(-100%)" : "translateY(0)", transition: "transform 320ms var(--easing-default)", fontWeight: 300, color: "var(--fg-muted)" }}>
          {isCopy ? t("→ click to copy") : isOpen ? t("→ click to open") : ""}
        </span>
      </span>
      <span className="channel-arrow" style={{ fontFamily: "var(--font-mono)", transform: hover && !isStatic ? "translateX(4px)" : "translateX(0)", transition: "transform 280ms", opacity: isStatic ? 0.3 : 1 }}>→</span>
    </button>
  );
}

function Contact() {
  useLang();
  return (
    <div className="page" style={{ paddingTop: 140 }}>
      <div className="page-eyebrow">
        <span className="micro">{t("Index")} 07</span>
        <span style={{ width: 24, height: 1, background: "var(--fg)" }} />
        <span className="micro micro-fg">{t("Contact · Open node")}</span>
      </div>

      {/* Marquee */}
      <div className="marquee-band" style={{ overflow: "hidden", borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)", padding: "16px 0", marginBottom: 80 }}>
        <div className="mobile-slow-marquee" style={{ display: "flex", gap: 48, whiteSpace: "nowrap", animation: "marqueeC 30s linear infinite" }}>
          {Array.from({ length: 8 }).map((_, i) => (
            <span key={i} className="micro" style={{ display: "inline-flex", alignItems: "center", gap: 16 }}>
              <span style={{ width: 6, height: 6, background: "var(--fg)", borderRadius: "50%" }} />
              {t("Available for · Collaboration · Research · Ideas · Co-conspiracy ·")}
            </span>
          ))}
        </div>
        <style>{`@keyframes marqueeC { from { transform: translateX(0); } to { transform: translateX(-50%); } }`}</style>
      </div>

      <div className="responsive-stack" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 64, marginBottom: 100 }}>
        <div>
          <h1 className="display-xl" style={{ marginBottom: 32 }}>
            {t("Open to connecting with builders and thinkers across disciplines.")}
          </h1>
          <p className="body-lg" style={{ color: "var(--fg-muted)", marginBottom: 24, maxWidth: 540 }}>
            {t("I read everything that comes in. The shorter and more specific the message, the faster I write back. If you're building something that touches physics, software, or culture — or all three — I want to hear from you.")}
          </p>
          <div className="micro" style={{ color: "var(--fg-muted)" }}>
            {t("Response time · usually 1–3 days · Korean or English")}
          </div>
        </div>
        <RadialCard />
      </div>

      {/* Channel rows */}
      <div style={{ marginBottom: 80 }}>
        {CHANNELS.map(c => <ChannelRow key={c.k} c={c} />)}
        <div style={{ borderTop: "1px solid var(--line-soft)" }} />
      </div>

      <div className="three-col" style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 32, padding: "48px 0", borderTop: "1px solid var(--line)" }}>
        <div>
          <div className="micro" style={{ marginBottom: 8 }}>{t("Mailing")}</div>
          <div className="body">{t("KAIST E6 (자연과학동)")}<br/>{t("291 Daehak-ro, Yuseong-gu")}<br/>{t("Daejeon 34141, KR")}</div>
        </div>
        <div>
          <div className="micro" style={{ marginBottom: 8 }}>{t("Hours")}</div>
          <div className="body">{t("Mon — Sat")}<br/>{t("10:00 — 22:00 KST")}<br/><span style={{ color: "var(--fg-muted)" }}>{t("Sundays read-only")}</span></div>
        </div>
        <div>
          <div className="micro" style={{ marginBottom: 8 }}>{t("Now")}</div>
          <div className="body">
            {t("Reading:")} <em>{t("Speed and Politics")}</em>{t(", Virilio")}<br/>
            {t("Watching: Bresson re-runs")}<br/>
            {t("Building: see /venture")}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Contact });
