/* ============================================================
   components.jsx — 공용 UI · 아이콘 · 게이지 · 별 배경
   ============================================================ */
const { useState, useEffect, useRef, useMemo } = React;

/* ---------- 라인 아이콘 ---------- */
const PATHS = {
  today:  "M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M18.4 5.6L17 7M7 17l-1.4 1.4M12 8a4 4 0 100 8 4 4 0 000-8z",
  saju:   "M5 4h4v16H5zM10 4h4v16h-4zM15 4h4v16h-4z",
  gunghap:"M12 20s-7-4.3-7-9.2A3.8 3.8 0 0112 8a3.8 3.8 0 017 2.8C19 15.7 12 20 12 20z",
  chat:   "M4 5h16v10H9l-4 4V5z",
  diary:  "M5 4h11a2 2 0 012 2v14H7a2 2 0 01-2-2V4zM9 4v16M16 8h-3M16 12h-3",
  moon:   "M20 14.5A8 8 0 119.5 4 6.5 6.5 0 0020 14.5z",
  spark:  "M12 3l1.6 5.6L19 10l-5.4 1.4L12 17l-1.6-5.6L5 10l5.4-1.4L12 3z",
  send:   "M12 20V5M6 11l6-6 6 6",
  back:   "M15 5l-7 7 7 7",
  plus:   "M12 5v14M5 12h14",
  user:   "M12 12a4 4 0 100-8 4 4 0 000 8zM5 20a7 7 0 0114 0",
  clock:  "M12 7v5l3 2M12 21a9 9 0 100-18 9 9 0 000 18z",
};
function Icon({ name, className }) {
  return (
    <svg className={"ico " + (className||"")} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
      <path d={PATHS[name]} />
    </svg>
  );
}

/* ---------- 원형 점수 게이지 ---------- */
function ScoreRing({ value, size = 132, stroke = 9, color = "var(--gold)", trackColor = "var(--track)", textColor = "var(--ivory)", labelColor = "var(--ivory-faint)", label, sub }) {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const [shown, setShown] = useState(0);
  useEffect(() => {
    let raf; const t0 = performance.now(); const dur = 1100;
    const tick = (t) => {
      const p = Math.min(1, (t - t0) / dur);
      const e = 1 - Math.pow(1 - p, 3);
      setShown(Math.round(value * e));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value]);
  return (
    <div style={{ position: "relative", width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size/2} cy={size/2} r={r} stroke={trackColor} strokeWidth={stroke} fill="none" />
        <circle cx={size/2} cy={size/2} r={r} stroke={color} strokeWidth={stroke} fill="none"
          strokeLinecap="round" strokeDasharray={c}
          strokeDashoffset={c - (c * shown) / 100}
          style={{ transition: "stroke-dashoffset .1s linear", filter: `drop-shadow(0 0 8px ${color}66)` }} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
        <div>
          <div className="serif" style={{ fontSize: size*0.34, lineHeight: 1, color: textColor }}>{shown}</div>
          {label && <div style={{ fontSize: 11, letterSpacing: ".2em", color: labelColor, marginTop: 6, textTransform: "uppercase" }}>{label}</div>}
        </div>
      </div>
      {sub && <div style={{ textAlign:"center", marginTop:10, fontSize:13, color:"var(--ivory-dim)" }}>{sub}</div>}
    </div>
  );
}

/* ---------- 운세 막대 ---------- */
function StatBar({ label, value, color = "var(--gold)" }) {
  const [w, setW] = useState(0);
  useEffect(() => { const t = setTimeout(() => setW(value), 120); return () => clearTimeout(t); }, [value]);
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
      <span style={{ width: 64, fontSize: 13, color: "var(--ivory-dim)", flex: "none" }}>{label}</span>
      <div style={{ flex: 1, height: 7, borderRadius: 99, background: "var(--track)", overflow: "hidden" }}>
        <div style={{ height: "100%", width: w + "%", borderRadius: 99, background: color,
          transition: "width 1s cubic-bezier(.2,.7,.2,1)" }} />
      </div>
      <span className="serif" style={{ width: 34, textAlign: "right", fontSize: 15, color: "var(--ivory)" }}>{value}</span>
    </div>
  );
}

/* ---------- 사주 기둥 표시 ---------- */
function PillarBlock({ p, label }) {
  if (!p) return (
    <div className="pillar empty">
      <div className="p-label">{label}</div>
      <div className="p-cell" style={{ opacity: .3 }}>—</div>
      <div className="p-cell" style={{ opacity: .3 }}>—</div>
    </div>
  );
  const elColor = (window.ELEMENTS[p.gan.el] || {}).color;
  const elColor2 = (window.ELEMENTS[p.zhi.el] || {}).color;
  return (
    <div className="pillar">
      <div className="p-label">{label}</div>
      <div className="p-cell" style={{ color: elColor }}>
        <span className="p-han">{p.gan.h}</span>
        <span className="p-ko">{p.gan.k} · {p.gan.el}</span>
      </div>
      <div className="p-cell" style={{ color: elColor2 }}>
        <span className="p-han">{p.zhi.h}</span>
        <span className="p-ko">{p.zhi.an}</span>
      </div>
    </div>
  );
}
function PillarRow({ saju }) {
  return (
    <div className="pillars">
      <PillarBlock p={saju.hour}  label="시주" />
      <PillarBlock p={saju.day}   label="일주" />
      <PillarBlock p={saju.month} label="월주" />
      <PillarBlock p={saju.year}  label="연주" />
    </div>
  );
}

/* ---------- 타이핑 점 ---------- */
function Typing() {
  return (
    <div className="typing">
      <span></span><span></span><span></span>
    </div>
  );
}

/* ---------- 별 배경 (vanilla canvas-free DOM) ---------- */
function mountStars() {
  const host = document.getElementById("stars");
  if (!host || host.dataset.on) return;
  host.dataset.on = "1";
  const N = 70;
  for (let i = 0; i < N; i++) {
    const s = document.createElement("div");
    const size = Math.random() * 2 + 0.6;
    s.style.cssText = `position:absolute;width:${size}px;height:${size}px;border-radius:50%;
      background:#F1ECE0;top:${Math.random()*100}%;left:${Math.random()*100}%;
      opacity:${Math.random()*0.6+0.1};
      animation:twinkle ${Math.random()*4+2.5}s ease-in-out ${Math.random()*4}s infinite;`;
    host.appendChild(s);
  }
}

/* ---------- localStorage 훅 ---------- */
function useStore(key, initial) {
  const [v, setV] = useState(() => {
    try { const raw = localStorage.getItem(key); return raw ? JSON.parse(raw) : initial; }
    catch { return initial; }
  });
  useEffect(() => { try { localStorage.setItem(key, JSON.stringify(v)); } catch {} }, [key, v]);
  return [v, setV];
}

Object.assign(window, {
  Icon, ScoreRing, StatBar, PillarBlock, PillarRow, Typing, mountStars, useStore,
});
