// Home page — rebuilt with 3D hero, animated KPI cards, SVG icons, parallax narrative

/* ---------- custom hook: scroll + intersection ---------- */
function useInView(options = { threshold: 0.15 }) {
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setInView(true); obs.disconnect(); }
    }, options);
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, inView];
}

function useScrollY() {
  const [y, setY] = React.useState(0);
  React.useEffect(() => {
    let raf = null;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => { setY(window.scrollY); raf = null; });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return y;
}

function useMouseTilt(intensity = 1) {
  const ref = React.useRef(null);
  const [t, setT] = React.useState({ rx: 0, ry: 0, mx: 0.5, my: 0.5 });
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const mx = (e.clientX - r.left) / r.width;
      const my = (e.clientY - r.top) / r.height;
      setT({
        ry: (mx - 0.5) * 12 * intensity,
        rx: -(my - 0.5) * 8 * intensity,
        mx, my,
      });
    };
    const onLeave = () => setT({ rx: 0, ry: 0, mx: 0.5, my: 0.5 });
    el.addEventListener("mousemove", onMove);
    el.addEventListener("mouseleave", onLeave);
    return () => { el.removeEventListener("mousemove", onMove); el.removeEventListener("mouseleave", onLeave); };
  }, [intensity]);
  return [ref, t];
}

/* ---------- 3D tilt hero background ---------- */
function HeroBackdrop({ tilt }) {
  // deterministic star field
  const stars = React.useMemo(() => {
    const arr = [];
    let seed = 7;
    const rnd = () => { seed = (seed * 9301 + 49297) % 233280; return seed / 233280; };
    for (let i = 0; i < 80; i++) {
      arr.push({
        x: rnd() * 100,
        y: rnd() * 100,
        z: rnd(),              // depth 0..1
        r: 0.3 + rnd() * 1.2,
        blink: rnd(),
      });
    }
    return arr;
  }, []);

  // years + milestones to plot
  const milestones = [
    { y: 2016, label: "출시" },
    { y: 2018, label: "정점" },
    { y: 2019, label: "마지막 업데이트" },
    { y: 2023, label: "마지막 리뷰" },
    { y: 2026, label: "아카이브" },
  ];

  const { rx, ry, mx, my } = tilt;

  return (
    <div className="hero-backdrop" aria-hidden="true">
      <div
        className="hero-3d-stage"
        style={{ transform: `perspective(1400px) rotateX(${rx}deg) rotateY(${ry}deg)` }}
      >
        {/* faint gradient floor */}
        <div className="hero-floor" />

        {/* star field, each star at its own z */}
        <div className="hero-stars">
          {stars.map((s, i) => (
            <span
              key={i}
              className="hero-star"
              style={{
                left: `${s.x}%`,
                top: `${s.y}%`,
                width: `${s.r * 2}px`,
                height: `${s.r * 2}px`,
                opacity: 0.15 + s.z * 0.7,
                transform: `translateZ(${s.z * 140}px)`,
                animationDelay: `${s.blink * 4}s`,
              }}
            />
          ))}
        </div>

        {/* big floating numerals, parallax */}
        <div className="hero-numeral hero-numeral-a" style={{ transform: `translateZ(40px) translate(${(mx-0.5)*-18}px, ${(my-0.5)*-10}px)` }}>2,200</div>
        <div className="hero-numeral hero-numeral-b" style={{ transform: `translateZ(90px) translate(${(mx-0.5)*-32}px, ${(my-0.5)*-18}px)` }}>2.6M</div>
        <div className="hero-numeral hero-numeral-c" style={{ transform: `translateZ(60px) translate(${(mx-0.5)*-24}px, ${(my-0.5)*-12}px)` }}>164</div>

        {/* timeline spine */}
        <svg className="hero-spine" viewBox="0 0 1400 120" preserveAspectRatio="none">
          <defs>
            <linearGradient id="spineGrad" x1="0" x2="1">
              <stop offset="0%" stopColor="var(--accent)" stopOpacity="0" />
              <stop offset="12%" stopColor="var(--accent)" stopOpacity="0.55" />
              <stop offset="50%" stopColor="var(--accent)" stopOpacity="0.9" />
              <stop offset="88%" stopColor="var(--accent)" stopOpacity="0.25" />
              <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
            </linearGradient>
          </defs>
          <line x1="0" y1="60" x2="1400" y2="60" stroke="url(#spineGrad)" strokeWidth="1.2" strokeDasharray="2 6" />
          {milestones.map((m, i) => {
            const x = (i / (milestones.length - 1)) * 1300 + 50;
            return (
              <g key={m.y}>
                <circle cx={x} cy={60} r="4" fill="var(--accent)" />
                <circle cx={x} cy={60} r="10" fill="none" stroke="var(--accent)" strokeOpacity="0.3" />
                <text x={x} y={36} textAnchor="middle" fontSize="11" fill="var(--fg-muted)" fontFamily="var(--font-mono)">{m.y}</text>
                <text x={x} y={88} textAnchor="middle" fontSize="10" fill="var(--fg-subtle)">{m.label}</text>
              </g>
            );
          })}
        </svg>

        {/* glow */}
        <div
          className="hero-glow"
          style={{ left: `${mx * 100}%`, top: `${my * 100}%` }}
        />
      </div>
    </div>
  );
}

/* ---------- narrative block with per-line parallax reveal ---------- */
function ParallaxNarrative({ lines }) {
  const [ref, inView] = useInView({ threshold: 0.12 });
  const scrollY = useScrollY();
  const [rectTop, setRectTop] = React.useState(null);

  React.useEffect(() => {
    if (!ref.current) return;
    const update = () => {
      const r = ref.current.getBoundingClientRect();
      setRectTop(r.top + window.scrollY);
    };
    update();
    window.addEventListener("resize", update);
    return () => window.removeEventListener("resize", update);
  }, [ref]);

  // local progress: 0 when top enters viewport bottom, 1 when bottom leaves viewport top
  const vh = typeof window === "undefined" ? 900 : window.innerHeight;
  const p = rectTop == null ? 0 : Math.max(0, Math.min(1, (scrollY + vh * 0.9 - rectTop) / (vh * 0.9)));

  return (
    <div ref={ref} className={"parallax-narrative " + (inView ? "is-visible" : "")}>
      {lines.map((line, i) => {
        const start = i / lines.length;
        const end = start + 0.35;
        const local = Math.max(0, Math.min(1, (p - start) / (end - start)));
        const y = (1 - local) * 40;
        const op = local;
        return (
          <p
            key={i}
            style={{
              transform: `translateY(${y}px)`,
              opacity: op,
              transition: "transform 700ms cubic-bezier(.2,.9,.2,1), opacity 700ms ease",
            }}
            dangerouslySetInnerHTML={{ __html: line }}
          />
        );
      })}
    </div>
  );
}

/* ---------- Mini visualizations that sit inside KPI cards ---------- */

// sparkline for downloads
function SparkMini({ data, accent = "var(--accent)", fill = true }) {
  const w = 140, h = 44;
  const max = Math.max(...data);
  const min = Math.min(...data);
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * (w - 4) + 2;
    const y = h - 4 - ((v - min) / (max - min || 1)) * (h - 8);
    return [x, y];
  });
  const path = pts.map((p, i) => (i === 0 ? "M" : "L") + p[0].toFixed(1) + "," + p[1].toFixed(1)).join(" ");
  const area = path + ` L${w-2},${h-2} L2,${h-2} Z`;
  return (
    <svg className="kpi-spark" viewBox={`0 0 ${w} ${h}`} width="100%" height={h}>
      <defs>
        <linearGradient id="sparkGradA" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={accent} stopOpacity="0.35" />
          <stop offset="100%" stopColor={accent} stopOpacity="0" />
        </linearGradient>
      </defs>
      {fill && <path d={area} fill="url(#sparkGradA)" />}
      <path d={path} fill="none" stroke={accent} strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]} r="2.6" fill={accent} />
    </svg>
  );
}

// animated star distribution (1~5 stars)
function StarDistMini() {
  const data = window.CHART_DATA.ratingDist; // [{rating,count,pct,color}]
  const byRating = {};
  data.forEach(d => { byRating[d.rating] = d; });
  const max = Math.max(...data.map(d => d.pct));
  const [ref, inView] = useInView();
  const rows = [5,4,3,2,1].map(r => byRating[r]);
  return (
    <div ref={ref} className="kpi-stars">
      {rows.map((r, i) => {
        const w = inView ? (r.pct / max) * 100 : 0;
        return (
          <div key={r.rating} className="kpi-star-row">
            <span className="kpi-star-label">
              {"★".repeat(r.rating)}<span className="kpi-star-dim">{"★".repeat(5 - r.rating)}</span>
            </span>
            <span className="kpi-star-bar">
              <span
                className="kpi-star-bar-fill"
                style={{
                  width: `${w}%`,
                  backgroundColor: r.color,
                  transitionDelay: `${i * 70}ms`,
                }}
              />
            </span>
            <span className="kpi-star-pct">{r.pct}%</span>
          </div>
        );
      })}
    </div>
  );
}

// flag grid that cycles + highlights
function FlagCloudMini() {
  const countries = window.CHART_DATA.topCountries;
  const [i, setI] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setI(x => (x + 1) % countries.length), 1600);
    return () => clearInterval(id);
  }, [countries.length]);
  return (
    <div className="kpi-flags">
      {countries.map((c, idx) => (
        <span
          key={c.code}
          className={"kpi-flag-chip" + (idx === i ? " is-active" : "")}
          title={`${c.name} · ${c.count.toLocaleString("ko-KR")}`}
          style={{ animationDelay: `${idx * 60}ms` }}
        >
          <span className="kpi-flag-emoji">{c.flag}</span>
          <span className="kpi-flag-count">{c.count.toLocaleString("ko-KR")}</span>
        </span>
      ))}
    </div>
  );
}

// activity dot matrix (7 years × 12 months approximation)
function ActivityMini() {
  // synthetic pulsing from 2016-02 .. 2023-11
  const months = [];
  // 8 years * 12 months = 96 dots
  for (let y = 2016; y <= 2023; y++) {
    for (let m = 0; m < 12; m++) {
      // activity index: rises to 2018 then decays
      const t = (y - 2016) * 12 + m;
      const peak = (2018 - 2016) * 12 + 5;
      const dist = Math.abs(t - peak);
      const a = Math.max(0, 1 - dist / 40);
      months.push(a);
    }
  }
  const [ref, inView] = useInView();
  return (
    <div ref={ref} className={"kpi-activity" + (inView ? " is-in" : "")}>
      {months.map((a, i) => (
        <span
          key={i}
          className="kpi-act-dot"
          style={{
            opacity: 0.08 + a * 0.92,
            transitionDelay: `${i * 4}ms`,
          }}
        />
      ))}
    </div>
  );
}

/* ---------- enhanced KPI card ---------- */
function EnhancedKpi({ value, label, annotation, format, extra }) {
  return (
    <div className="kpi-card kpi-card-enhanced">
      <div className="kpi-value"><CountUp end={value} format={format} /></div>
      <div className="kpi-label">{label}</div>
      {extra && <div className="kpi-extra">{extra}</div>}
      {annotation && (
        <div className="kpi-annotation">
          <span>↑</span>
          <span>{annotation}</span>
        </div>
      )}
    </div>
  );
}

/* ---------- entry card SVG icons (replaces emoji) ---------- */
const ENTRY_ICONS = {
  stories: (
    <svg viewBox="0 0 48 48" fill="none" className="entry-svg">
      <path d="M8 10 C8 8 9 7 11 7 L22 7 L24 10 L24 41 L11 41 C9 41 8 40 8 38 Z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round" />
      <path d="M40 10 C40 8 39 7 37 7 L26 7 L24 10 L24 41 L37 41 C39 41 40 40 40 38 Z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round" />
      <path d="M12 14 L20 14 M12 19 L20 19 M12 24 L18 24" stroke="currentColor" strokeWidth="1" strokeLinecap="round" opacity="0.55" />
      <path d="M28 14 L36 14 M28 19 L36 19 M28 24 L34 24" stroke="currentColor" strokeWidth="1" strokeLinecap="round" opacity="0.55" />
      <circle cx="24" cy="32" r="2.2" fill="currentColor" />
    </svg>
  ),
  reviews: (
    <svg viewBox="0 0 48 48" fill="none" className="entry-svg">
      <rect x="6" y="9" width="36" height="30" rx="3" stroke="currentColor" strokeWidth="1.4" />
      <rect x="11" y="26" width="4" height="8" rx="1" fill="currentColor" opacity="0.45" />
      <rect x="18" y="20" width="4" height="14" rx="1" fill="currentColor" opacity="0.7" />
      <rect x="25" y="15" width="4" height="19" rx="1" fill="currentColor" />
      <rect x="32" y="22" width="4" height="12" rx="1" fill="currentColor" opacity="0.55" />
      <path d="M11 15 L15 17 L22 13 L29 15 L36 12" stroke="currentColor" strokeWidth="1" opacity="0.35" />
    </svg>
  ),
  sales: (
    <svg viewBox="0 0 48 48" fill="none" className="entry-svg">
      <circle cx="24" cy="24" r="17" stroke="currentColor" strokeWidth="1.4" />
      <path d="M7 24 H41" stroke="currentColor" strokeWidth="1" opacity="0.5" />
      <path d="M24 7 C16 12 16 36 24 41" stroke="currentColor" strokeWidth="1" opacity="0.5" />
      <path d="M24 7 C32 12 32 36 24 41" stroke="currentColor" strokeWidth="1" opacity="0.5" />
      <circle cx="20" cy="16" r="1.5" fill="currentColor" />
      <circle cx="30" cy="22" r="1.5" fill="currentColor" />
      <circle cx="17" cy="30" r="1.5" fill="currentColor" />
      <circle cx="32" cy="33" r="1.5" fill="currentColor" />
    </svg>
  ),
  timeline: (
    <svg viewBox="0 0 48 48" fill="none" className="entry-svg">
      <path d="M8 24 H40" stroke="currentColor" strokeWidth="1.4" />
      <circle cx="12" cy="24" r="3" fill="currentColor" />
      <circle cx="22" cy="24" r="2.5" stroke="currentColor" strokeWidth="1.4" fill="none" />
      <circle cx="32" cy="24" r="2.5" stroke="currentColor" strokeWidth="1.4" fill="none" />
      <circle cx="40" cy="24" r="2" fill="currentColor" />
      <path d="M12 24 V14 M22 24 V34 M32 24 V14 M40 24 V34" stroke="currentColor" strokeWidth="1" opacity="0.45" />
      <text x="12" y="11" fontFamily="var(--font-mono)" fontSize="5" textAnchor="middle" fill="currentColor" opacity="0.7">16</text>
      <text x="22" y="40" fontFamily="var(--font-mono)" fontSize="5" textAnchor="middle" fill="currentColor" opacity="0.7">18</text>
      <text x="32" y="11" fontFamily="var(--font-mono)" fontSize="5" textAnchor="middle" fill="currentColor" opacity="0.7">19</text>
      <text x="40" y="40" fontFamily="var(--font-mono)" fontSize="5" textAnchor="middle" fill="currentColor" opacity="0.7">26</text>
    </svg>
  ),
  versions: (
    <svg viewBox="0 0 48 48" fill="none" className="entry-svg">
      <circle cx="14" cy="14" r="3" stroke="currentColor" strokeWidth="1.4" />
      <circle cx="14" cy="28" r="3" stroke="currentColor" strokeWidth="1.4" />
      <circle cx="34" cy="34" r="3" fill="currentColor" />
      <path d="M14 17 V25" stroke="currentColor" strokeWidth="1.4" />
      <path d="M14 31 C14 34 20 34 24 34 L31 34" stroke="currentColor" strokeWidth="1.4" fill="none" />
      <path d="M17 14 C24 14 28 14 28 22 L28 28" stroke="currentColor" strokeWidth="1.4" fill="none" opacity="0.55" />
      <circle cx="28" cy="31" r="2" stroke="currentColor" strokeWidth="1.4" opacity="0.55" />
    </svg>
  ),
  screenshots: (
    <svg viewBox="0 0 48 48" fill="none" className="entry-svg">
      <rect x="10" y="8" width="18" height="30" rx="2.5" stroke="currentColor" strokeWidth="1.4" />
      <rect x="22" y="12" width="18" height="30" rx="2.5" stroke="currentColor" strokeWidth="1.4" fill="var(--bg-surface)" />
      <circle cx="31" cy="37" r="1" fill="currentColor" opacity="0.6" />
      <path d="M25 20 H37 M25 24 H34 M25 28 H37 M25 32 H32" stroke="currentColor" strokeWidth="1" opacity="0.45" />
    </svg>
  ),
};

/* ---------- HomePage ---------- */
function HomePage({ setPage }) {
  const data = window.ARCHIVE_DATA;
  const chart = window.CHART_DATA;
  const [heroRef, tilt] = useMouseTilt(1);
  const scrollY = useScrollY();

  // Parallax offsets for hero text (mild)
  const titleShift = Math.min(scrollY * 0.15, 60);
  const titleOpacity = Math.max(0, 1 - scrollY / 500);

  // Build KPI extras
  const downloadTrend = [
    120, 220, 380, 580, 780, 930, 760, 540, 380, 260, 180, 120, 80, 55, 40, 28, 20, 14, 10, 8,
  ];
  const reviewTrend = chart.monthlyReviews.map(m => m.v);

  return (
    <div>
      {/* HERO with 3D backdrop */}
      <section ref={heroRef} className="hero hero-v2">
        <HeroBackdrop tilt={tilt} />
        <div
          className="hero-content"
          style={{ transform: `translateY(${titleShift}px)`, opacity: titleOpacity }}
        >
          <div className="hero-eyebrow">Todait Archive · 2016 — 2026</div>
          <h1 className="hero-title">
            투데잇이라는 이름으로<br/>보낸 <em>10년</em>
          </h1>
          <div className="hero-dates">
            <span>2016 · 02 · 10</span>
            <span className="line" />
            <span className="dot" />
            <span className="line" />
            <span>2026 · 04 · 24</span>
          </div>
          <div className="hero-lede">
            <p>2016년 2월 10일, 첫 빌드가 Apple 서버에 올라갔다. 2019년 9월 25일, 마지막 업데이트가 있었다.</p>
            <p>그 사이에 2,200명이 리뷰를 썼고, 261만 번의 다운로드가 있었다.</p>
          </div>
          <div className="hero-scroll-hint">↓ 스크롤</div>
        </div>
      </section>

      {/* RICH KPI GRID */}
      <section className="page" style={{ marginTop: 120 }}>
        <div className="kpi-grid kpi-grid-rich">
          {/* downloads w/ sparkline */}
          <EnhancedKpi
            value={2613906}
            label="총 다운로드"
            format="exact"
            annotation="2018 정점 · 월 93만"
            extra={
              <div className="kpi-mini">
                <SparkMini data={downloadTrend} accent="var(--brand-mint-500)" />
                <div className="kpi-mini-axis">
                  <span>2016</span><span>2018</span><span>2020</span><span>2023</span>
                </div>
              </div>
            }
          />

          {/* reviews w/ star distribution */}
          <EnhancedKpi
            value={2200}
            label="남겨진 리뷰"
            format="exact"
            annotation="★ 평균 3.84"
            extra={<StarDistMini />}
          />

          {/* countries w/ flag cloud */}
          <EnhancedKpi
            value={164}
            label="리뷰가 도착한 나라"
            format="exact"
            annotation="대한민국 비중 89.9%"
            extra={<FlagCloudMini />}
          />

          {/* active period w/ activity matrix */}
          <EnhancedKpi
            value={"7년 5개월"}
            label="활동한 기간"
            format="text"
            annotation="2016-02 ~ 2023-11"
            extra={<ActivityMini />}
          />
        </div>
      </section>

      {/* PARALLAX OPENING NARRATIVE */}
      <section className="page-narrow section">
        <div className="narrative-eyebrow">여는 글</div>
        <ParallaxNarrative lines={[
          "<strong>2016년 2월 10일</strong>, 첫 빌드가 Apple 서버에 올라갔다. <strong>2019년 9월 25일</strong>, 마지막 업데이트가 있었다. 그 사이에 <em>2,200명</em>이 리뷰를 썼고, <em>261만 번</em>의 다운로드가 있었다.",
          "이 앱에 별점을 남긴 <em>16,652명</em> 중 글까지 쓴 사람은 <em>2,200명</em>이다. 나머지 14,452명의 감정은 별 하나, 둘, 셋, 넷, 다섯으로만 남았다.",
          "이 아카이브는 그 2,200명의 목소리와, 별점만 남긴 나머지 사람들의 평균값을 함께 기억하기 위한 기록이다.",
        ]} />
      </section>

      {/* ENTRY CARDS with SVG icons */}
      <section className="page section">
        <h2 className="section-title">앞으로 만날 기록들</h2>
        <p className="section-sub">여섯 개의 문을 열고 들어가면, 각자 다른 시간으로 이어진다.</p>
        <div className="entry-grid entry-grid-v2">
          {data.entryCards.map((e, idx) => (
            <button
              key={e.key}
              className={"entry-card entry-card-v2 entry-card-" + e.key}
              style={{ animationDelay: `${idx * 60}ms` }}
              onClick={() => setPage(e.key)}
            >
              <div className="entry-card-icon-wrap">
                {ENTRY_ICONS[e.key] || <span style={{fontSize:28}}>{e.icon}</span>}
              </div>
              <div className="entry-card-title">{e.title}</div>
              <div className="entry-card-desc">{e.desc}</div>
              <div className="entry-card-cta">{e.cta} →</div>
            </button>
          ))}
        </div>
      </section>

      {/* EPILOGUE TEASER */}
      <section className="page epilogue">
        <div className="epilogue-quote">"그리고 마지막 말이 남았다."</div>
        <button className="epilogue-link" onClick={() => setPage("stories")}>
          스토리 · 해외의 목소리로 →
        </button>
      </section>
    </div>
  );
}

Object.assign(window, { HomePage, useInView, useScrollY, useMouseTilt, ParallaxNarrative, StarDistMini, FlagCloudMini, SparkMini, ActivityMini });
