/* ============================================================
   app.jsx — root, routing, theme, tweaks
   ============================================================ */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "blogName": "Kai",
  "accent": "#bf4d28",
  "fontScale": 19.5,
  "readWidth": 680
}/*EDITMODE-END*/;

function parseHash() {
  let h = window.location.hash || "#/";
  if (!h.startsWith("#")) h = "#/" + h;
  const [path, query] = h.slice(1).split("?");
  const params = new URLSearchParams(query || "");
  const parts = path.split("/").filter(Boolean); // e.g. ["p","slug"]
  if (parts[0] === "p" && parts[1]) return { name: "article", slug: parts[1] };
  if (parts[0] === "about") return { name: "about" };
  return { name: "home", tag: params.get("tag") || null };
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const posts = window.POSTS;

  const [route, setRoute] = useState(parseHash());
  const [theme, setTheme] = useState(() => localStorage.getItem("blog-theme") || "light");
  const [searchOpen, setSearchOpen] = useState(false);
  const [tag, setTagState] = useState(route.tag);

  // routing
  useEffect(() => {
    const onHash = () => {
      const r = parseHash();
      setRoute(r);
      if (r.name === "home") setTagState(r.tag);
      window.scrollTo({ top: 0, behavior: "auto" });
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  const nav = useCallback((hash) => {
    if (window.location.hash === hash) {
      // same route — force scroll top
      window.scrollTo({ top: 0, behavior: "smooth" });
    }
    window.location.hash = hash;
  }, []);

  // theme
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
    localStorage.setItem("blog-theme", theme);
  }, [theme]);
  const toggleTheme = () => setTheme(th => th === "dark" ? "light" : "dark");

  // tweaks -> css vars
  useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty("--accent", t.accent);
    root.style.setProperty("--read", t.readWidth + "px");
    document.body.style.fontSize = "19px"; // base ui
  }, [t.accent, t.readWidth]);

  // search hotkey
  useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault(); setSearchOpen(s => !s);
      } else if (e.key === "/" && !/INPUT|TEXTAREA/.test(document.activeElement.tagName)) {
        e.preventDefault(); setSearchOpen(true);
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  const setTag = (tg) => {
    setTagState(tg);
    window.location.hash = tg ? "#/?tag=" + tg : "#/";
  };

  const blogName = t.blogName || "Kai";
  const article = route.name === "article" ? posts.find(p => p.slug === route.slug) : null;

  return (
    <div className="shell" style={{ "--prose-size": t.fontScale + "px" }}>
      <Masthead route={route} nav={nav} onSearch={() => setSearchOpen(true)}
                theme={theme} toggleTheme={toggleTheme} blogName={blogName} />

      <main style={{ "--prose-size": t.fontScale + "px" }}>
        {route.name === "home" &&
          <HomeView posts={posts} nav={nav} activeTag={tag} setTag={setTag} blogName={blogName} />}
        {route.name === "about" &&
          <AboutView blogName={blogName} nav={nav} />}
        {route.name === "article" && article &&
          <ProseScale size={t.fontScale}><ArticleView post={article} posts={posts} nav={nav} blogName={blogName} /></ProseScale>}
        {route.name === "article" && !article &&
          <div className="wrap" style={{ padding: "100px 0" }}>
            <h1 style={{ fontWeight: 500 }}>Not found</h1>
            <p style={{ color: "var(--muted)" }}>That post doesn't exist. <a className="link" onClick={() => nav("#/")} style={{ cursor: "pointer" }}>Back to writing →</a></p>
          </div>}
      </main>

      <SiteFoot blogName={blogName} nav={nav} />

      {searchOpen && <SearchModal posts={posts} nav={nav} close={() => setSearchOpen(false)} />}

      <TweaksPanel>
        <TweakSection label="Identity" />
        <TweakText label="Blog name" value={t.blogName} onChange={v => setTweak("blogName", v)} />
        <TweakColor label="Accent" value={t.accent}
                    options={["#bf4d28", "#2f6fb0", "#4f46e5", "#1f7a4d", "#9d2449", "#7c3aed"]}
                    onChange={v => setTweak("accent", v)} />
        <TweakSection label="Reading" />
        <TweakSlider label="Body size" value={t.fontScale} min={16} max={23} step={0.5} unit="px"
                     onChange={v => setTweak("fontScale", v)} />
        <TweakSlider label="Measure" value={t.readWidth} min={580} max={780} step={10} unit="px"
                     onChange={v => setTweak("readWidth", v)} />
      </TweaksPanel>
    </div>
  );
}

// applies the reading font size to .prose via a style tag scoped to article
function ProseScale({ size, children }) {
  useEffect(() => {
    let el = document.getElementById("__prose-scale");
    if (!el) { el = document.createElement("style"); el.id = "__prose-scale"; document.head.appendChild(el); }
    el.textContent = ".prose{font-size:" + size + "px}";
  }, [size]);
  return children;
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
