// d4not — cards, drawer, submit modal, safety modal

function projectHref(project) {
  return "project.html?slug=" + encodeURIComponent(project.slug || project.id);
}

function ProjectCard({ project, surface, idx, onOpen }) {
  const tokens = (project.meta && project.meta.tokens) || 0;
  const href = projectHref(project);
  const btnStyle = { padding: "6px 10px", fontSize: 11, flex: 1, textAlign: "center" };
  return (
    <article className="card" style={{ cursor: "default" }}>
      <div className="cover">
        {project.cover_url
          ? (() => {
              const isAvatar = /avatars\.githubusercontent\.com/.test(project.cover_url);
              return <img src={project.cover_url} alt=""
                 style={{
                   position:"absolute", inset:0, width:"100%", height:"100%",
                   objectFit: isAvatar ? "contain" : "cover",
                   padding: isAvatar ? 14 : 0,
                   background: isAvatar ? "var(--bg-3)" : "transparent"
                 }} />;
            })()
          : <>
              <div className="halftone" />
              <div className="glyph">{surface.glyph}</div>
            </>}
        <div className="badge">{surface.label}</div>
        <div className={"trust trust-" + project.trust}>
          {project.trust === "reviewed" ? "✓ reviewed" :
           project.trust === "automated" ? "◐ scan ok" : "! unverified"}
        </div>
        <div className={"host " + project.host}>
          <span className="dot" />{hostLabel(project.host)}
        </div>
      </div>
      <div className="body">
        <div className="pre">
          <span>№ {String(idx+1).padStart(3,"0")} · {project.slug || project.id.slice(0,8)}</span>
          <span>{relTime(project.added_at)}</span>
        </div>
        <h3 className="title">{project.title}</h3>
        <p className="blurb">{project.blurb}</p>
        <div className="stacks-row">
          {(project.stacks||[]).slice(0,3).map(s => <Tag key={s}>{s}</Tag>)}
          {project.origin === "ai" && <Tag variant="red">AI</Tag>}
          {project.origin === "hybrid" && <Tag variant="y">HYBRID</Tag>}
        </div>
      </div>
      <div className="footer">
        <a href={"profile.html?handle=" + encodeURIComponent(project.author_handle || "")}
           onClick={e => e.stopPropagation()}
           style={{ color: "inherit", textDecoration: "underline", textUnderlineOffset: 2 }}>
          @{project.author_handle}
        </a>
        <div className="stats">
          {tokens > 0 && <span>⌬ <b>{fmtTokens(tokens)}</b></span>}
          {project.stars != null && <span>★ <b>{fmt(project.stars)}</b></span>}
          <span>⑂ <b>{fmt(project.forks)}</b></span>
        </div>
      </div>
      <div style={{ display: "flex", gap: 8, padding: "10px 14px", borderTop: "1px solid var(--rule-2)" }}>
        <button className="btn" onClick={() => onOpen(project)} style={btnStyle}>👁 Preview</button>
        <a className="btn primary" href={href} style={btnStyle}>→ Open</a>
      </div>
    </article>
  );
}

function ListRow({ project, surface, idx, onOpen }) {
  const href = projectHref(project);
  return (
    <article className="card" style={{ cursor: "default" }}>
      <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--ink-4)" }}>
        {String(idx+1).padStart(3,"0")}
      </div>
      <div className="body">
        <h3 className="title">{project.title}</h3>
        <p className="blurb">{project.blurb}</p>
      </div>
      <div className="stacks-row">
        <Tag>{surface.label}</Tag>
        {(project.stacks||[]).slice(0,2).map(s => <Tag key={s}>{s}</Tag>)}
      </div>
      <div className="numc">
        <div><a href={"profile.html?handle=" + encodeURIComponent(project.author_handle || "")}
               onClick={e => e.stopPropagation()}
               style={{ color: "inherit", textDecoration: "underline", textUnderlineOffset: 2 }}>
          @{project.author_handle}
        </a></div>
        <div style={{ fontSize: 10.5, color: "var(--ink-3)", marginTop: 4 }}>
          <span className={"trust-" + project.trust} style={{ padding: "1px 5px", fontSize: 9.5, letterSpacing: "0.08em" }}>
            {project.trust === "reviewed" ? "✓" : project.trust === "automated" ? "◐" : "!"}
          </span>
          &nbsp; ⑂ {fmt(project.forks)} &nbsp; ★ {fmt(project.stars)}
        </div>
      </div>
      <div className="numc" style={{ display: "flex", gap: 6, justifyContent: "flex-end" }}>
        <button className="btn" onClick={() => onOpen(project)} style={{ padding: "4px 8px", fontSize: 11 }}>👁 Preview</button>
        <a className="btn primary" href={href} style={{ padding: "4px 8px", fontSize: 11 }}>→ Open</a>
      </div>
    </article>
  );
}

function Catalog({
  results, sort, setSort, view, setView,
  activeChips, onClearAll, onClearChip,
  query, onQuery,
}) {
  const surfaceById = useMemo(() => {
    const m = {}; window.SURFACES.forEach(s => m[s.id] = s); return m;
  }, []);
  const [openProject, setOpenProject] = useState(null);

  return (
    <section className="catalog">
      <div className="toolbar">
        <div className="crumb">
          THE STACKS
          <span className="tot">— {results.length} works indexed</span>
        </div>
        <div style={{ flex: 1, display: "flex", alignItems: "center", background: "var(--panel)", border: "1px solid var(--rule-2)", maxWidth: 340 }}>
          <span style={{ padding: "0 10px", fontFamily: "var(--mono)", color: "var(--red)", fontSize: 13 }}>&gt;</span>
          <input
            value={query} onChange={e => onQuery(e.target.value)}
            placeholder='search catalog…'
            style={{
              flex: 1, padding: "9px 8px 9px 0",
              fontFamily: "var(--mono)", fontSize: 13,
              background: "transparent", border: 0,
              color: "var(--ink)", outline: "none",
            }}
          />
          {query && (
            <button onClick={() => onQuery("")}
              style={{ padding: "0 10px", fontFamily: "var(--mono)", fontSize: 12, color: "var(--ink-3)" }}>✕</button>
          )}
        </div>
        <div className="right">
          <span>Sort</span>
          <select value={sort} onChange={e => setSort(e.target.value)}>
            <option value="recent">Most recent</option>
            <option value="saves">Most saved</option>
            <option value="forks">Most forked</option>
            <option value="stars">Most stars</option>
            <option value="tokens">Token-savings</option>
            <option value="alpha">A → Z</option>
          </select>
          <div className="viewtoggle">
            <button className={view === "gallery" ? "on" : ""} onClick={() => setView("gallery")}>Gallery</button>
            <button className={view === "dense"   ? "on" : ""} onClick={() => setView("dense")}>Dense</button>
            <button className={view === "list"    ? "on" : ""} onClick={() => setView("list")}>List</button>
            <button className={view === "masonry" ? "on" : ""} onClick={() => setView("masonry")}>Masonry</button>
          </div>
        </div>
      </div>

      {activeChips.length > 0 && (
        <div className="activebar">
          <span>Filtering:</span>
          {activeChips.map(c => (
            <button key={c.key} className="chip on" onClick={() => onClearChip(c)}>{c.label} ✕</button>
          ))}
          <span className="clear" onClick={onClearAll}>Clear all</span>
        </div>
      )}

      {results.length === 0 ? (
        <div className="empty">
          <div className="big">∅</div>
          <h3>Nothing indexed for that.</h3>
          <div>Which is exactly why you should build it, push it, and submit the link.</div>
        </div>
      ) : view === "list" ? (
        <div className="list">
          {results.map((p, i) => <ListRow key={p.id} project={p} surface={surfaceById[p.surface]} idx={i} onOpen={setOpenProject} />)}
        </div>
      ) : (
        <div className={"grid " + (view === "dense" ? "dense" : view === "masonry" ? "masonry" : "")}>
          {results.map((p, i) => <ProjectCard key={p.id} project={p} surface={surfaceById[p.surface]} idx={i} onOpen={setOpenProject} />)}
        </div>
      )}

      <DetailDrawer project={openProject} onClose={() => setOpenProject(null)} />
    </section>
  );
}

function DetailDrawer({ project, onClose }) {
  const open = !!project;
  const [drawerTab, setDrawerTab] = useState("info");

  useEffect(() => {
    function onKey(e) { if (e.key === "Escape") onClose(); }
    if (open) window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose]);

  // reset tab on project change
  useEffect(() => { setDrawerTab("info"); }, [project?.id]);

  if (!project) return <><div className="scrim" /><aside className="drawer" /></>;

  const surface = window.SURFACES.find(s => s.id === project.surface) || { label: project.surface };
  const trust   = window.TRUST.find(t => t.id === project.trust) || { label: project.trust, note: "" };
  const url     = window.hostUrl(project);
  const originLbl = project.origin === "ai" ? "AI-built" : project.origin === "hybrid" ? "Hybrid" : "Hand-crafted";
  const license = (project.meta && project.meta.license) || "—";
  const fullHref = "project.html?slug=" + encodeURIComponent(project.slug || project.id);

  return (
    <>
      <div className={"scrim" + (open ? " on" : "")} onClick={onClose} />
      <aside className={"drawer" + (open ? " on" : "")}>
        <div className="head">
          <div className="top">
            <span>{surface.label} · {project.slug || project.id.slice(0,8)}</span>
            <button onClick={onClose} style={{ color: "var(--ink-3)", fontFamily: "var(--mono)", fontSize: 12 }}>Close ✕</button>
          </div>
          <h2>{project.title}</h2>
          <p className="blurb">{project.blurb}</p>
          <div className="tags">
            <Tag variant="solid">{surface.label}</Tag>
            {(project.stacks||[]).map(s => <Tag key={s}>{s}</Tag>)}
            <Tag variant={project.origin === "ai" ? "red" : project.origin === "hybrid" ? "y" : "solid"}>{originLbl}</Tag>
            <Tag>{license}</Tag>
          </div>
          <div style={{ marginTop: 14 }}>
            <a href={fullHref}
               style={{ display: "inline-block", fontFamily: "var(--mono)", fontSize: 11,
                        letterSpacing: "0.12em", textTransform: "uppercase",
                        color: "var(--red)", textDecoration: "none",
                        borderBottom: "1px solid var(--red)", paddingBottom: 2 }}>
              Open full page →
            </a>
          </div>
          {/* drawer tabs */}
          <div className="forum-tabs" style={{ marginTop: 16, marginBottom: 0 }}>
            <button className={drawerTab === "info" ? "on" : ""} onClick={() => setDrawerTab("info")}>Info</button>
            <button className={drawerTab === "use"  ? "on" : ""} onClick={() => setDrawerTab("use")}>Use it</button>
          </div>
        </div>

        <div className="body">
          {drawerTab === "info" && <InfoTab project={project} surface={surface} trust={trust} url={url} />}
          {drawerTab === "use"  && <UseTab project={project} url={url} />}
        </div>
      </aside>
    </>
  );
}

function InfoTab({ project, surface, trust, url }) {
  const license = (project.meta && project.meta.license) || "—";
  const model   = (project.meta && project.meta.model)   || "—";
  const tokens  = (project.meta && project.meta.tokens)  || 0;
  const repoShort = (() => {
    try { return new URL(project.repo_url || "").pathname.replace(/^\/+|\/+$/g,""); }
    catch { return project.repo_url || ""; }
  })();
  return <>
    <div className="actions-row">
      <a className="btn primary" href={url} target="_blank" rel="noopener noreferrer">
        ↗ Open on {hostLabel(project.host)}
      </a>
      <a className="btn yellow" href={"project.html?slug=" + encodeURIComponent(project.slug || project.id)}>
        View full page →
      </a>
    </div>

    <div className="trust-panel">
      <span className={"badge trust-" + project.trust}>
        {project.trust === "reviewed" ? "✓ Reviewed" : project.trust === "automated" ? "◐ Scanned" : "! Unverified"}
      </span>
      <div>
        <h4>{trust.label}</h4>
        <p>
          {trust.note}
          {project.trust !== "reviewed" && <> &nbsp;d4not <b style={{color:"var(--red)"}}>assumes no liability</b>.</>}
        </p>
      </div>
    </div>

    <div className="spec-grid">
      <div><div className="k">Author</div><div className="v"><a href={"profile.html?handle=" + encodeURIComponent(project.author_handle || "")} style={{ color: "inherit", textDecoration: "underline", textUnderlineOffset: 2 }}>@{project.author_handle}</a></div></div>
      <div><div className="k">Indexed</div><div className="v">{fmtDate(project.added_at)}</div></div>
      <div><div className="k">Source</div><div className="v"><span className="mono">{hostLabel(project.host)} · {repoShort}</span></div></div>
      <div><div className="k">License</div><div className="v">{license}</div></div>
      <div><div className="k">Built with</div><div className="v"><span className="mono">{model}</span></div></div>
      <div>
        <div className="k">Tokens to regenerate</div>
        <div className="v" style={{ color: tokens > 0 ? "var(--red)" : "var(--ink-3)" }}>
          <span className="mono">{tokens > 0 ? "≈ " + fmtTokens(tokens) : "—"}</span>
        </div>
      </div>
    </div>
  </>;
}

function UseTab({ project, url }) {
  const key = project.slug || project.id;
  return <>
    <div>
      <div style={{ fontFamily: "var(--mono)", fontSize: 10.5, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--ink-3)", marginBottom: 8 }}>
        Use from your prompt
      </div>
      <div className="code-window">
        <div className="top"><span>prompt.txt</span><span style={{ cursor: "pointer" }}>copy</span></div>
        <pre>{`> start from d4not://${key} (${project.title})
> repo: ${url}
> modify `}<span className="c-key">src/</span>{` for the new `}<span className="c-com">{`<feature>`}</span>{`
> keep existing component vocabulary & tokens`}
        </pre>
      </div>
    </div>
    <div className="code-window">
      <div className="top"><span>clone</span><span>bash</span></div>
      <pre><span className="c-com"># clone via {hostLabel(project.host)}</span>{`
$ git clone `}<span className="c-str">{url}</span>
      </pre>
    </div>
    <div style={{ fontFamily: "var(--sans)", fontSize: 13.5, color: "var(--ink-3)", fontStyle: "italic", lineHeight: 1.55 }}>
      d4not library doesn't host this code. The link above goes to the author's repository.
      Always audit before running. <a href="safety.html" style={{ color: "var(--red)" }}>Safety policy →</a>
    </div>
  </>;
}

function SubmitModal({ open, onClose }) {
  const [url, setUrl]     = useState("");
  const [title, setTitle] = useState("");
  const [blurb, setBlurb] = useState("");
  const [surface, setSurface] = useState("");
  const [origin, setOrigin]   = useState("");
  const [stacks, setStacks]   = useState("");
  const [license, setLicense] = useState("");
  const [model, setModel]     = useState("");
  const [prompt, setPrompt]   = useState("");
  const [state, setState]     = useState("idle"); // idle | submitting | done | error
  const [errMsg, setErrMsg]   = useState("");
  const [publishedSlug, setPublishedSlug] = useState(null);

  async function submit() {
    setErrMsg("");
    if (!url.trim())   { setErrMsg("Repo URL is required."); return; }
    if (!title.trim()) { setErrMsg("Title is required.");    return; }
    setState("submitting");
    try {
      const stackList = stacks.split(",").map(s => s.trim()).filter(Boolean);
      const row = await window.D4API.publishProject({
        repo_url: url.trim(),
        title:   title.trim(),
        blurb:   blurb.trim(),
        surface: surface || "app",
        origin:  origin || "ai",
        stacks:  stackList,
        license, model, prompt,
      });
      setPublishedSlug(row.slug);
      setState("done");
    } catch (e) {
      setState("error");
      setErrMsg(e.message || "Could not publish.");
    }
  }

  function reset() {
    setUrl(""); setTitle(""); setBlurb(""); setSurface(""); setOrigin("");
    setStacks(""); setLicense(""); setModel(""); setPrompt("");
    setState("idle"); setErrMsg(""); setPublishedSlug(null);
  }

  return (
    <div className={"modal-scrim" + (open ? " on" : "")} onClick={() => { reset(); onClose(); }}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="head">
          <h3>Publish your project</h3>
          <span className="x" onClick={() => { reset(); onClose(); }}>close ✕</span>
        </div>
        {state === "done" ? (
          <div className="body">
            <div style={{ padding: "22px 0", textAlign: "center" }}>
              <div style={{ fontFamily: "var(--display)", fontSize: 32, color: "var(--lime)", marginBottom: 10 }}>✓ Published</div>
              <p className="intro" style={{ textAlign: "center" }}>
                Your project is live as <b style={{ color: "var(--yellow)" }}>unverified</b>. A maintainer will review it
                for a "reviewed" badge within a few days.
              </p>
              <div style={{ marginTop: 16 }}>
                <a className="btn primary" href={"project.html?slug=" + encodeURIComponent(publishedSlug || "")}>
                  Open your project page →
                </a>
              </div>
            </div>
          </div>
        ) : (
        <div className="body">
          <p className="intro">
            d4not library doesn't host files — you keep your repo on GitHub / GitLab / Codeberg / etc.
            We index the link, route traffic, and let people discuss it in the project forum.
            Your project goes live immediately as <b style={{ color: "var(--yellow)" }}>unverified</b>;
            a maintainer upgrades trust later after a read-through.
          </p>

          <label><span>Repo URL (full https://…)</span>
            <input type="url" value={url} onChange={e => setUrl(e.target.value)}
                   placeholder="https://github.com/owner/project" />
          </label>

          <label><span>Title</span>
            <input type="text" value={title} onChange={e => setTitle(e.target.value)} placeholder="Quietframe" />
          </label>
          <label><span>One-line description</span>
            <input type="text" value={blurb} onChange={e => setBlurb(e.target.value)}
                   placeholder="Keyboard-first writing app with focus mode." />
          </label>

          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <label><span>Surface</span>
              <select value={surface} onChange={e => setSurface(e.target.value)}>
                <option value="">—</option>
                {window.SURFACES.map(s => <option key={s.id} value={s.id}>{s.label}</option>)}
              </select>
            </label>
            <label><span>Origin</span>
              <select value={origin} onChange={e => setOrigin(e.target.value)}>
                <option value="">—</option>
                {window.ORIGINS.map(o => <option key={o.id} value={o.id}>{o.label}</option>)}
              </select>
            </label>
          </div>

          <label><span>Stacks (comma-separated)</span>
            <input type="text" value={stacks} onChange={e => setStacks(e.target.value)}
                   placeholder="React, TypeScript, Tailwind" />
          </label>

          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <label><span>License</span>
              <input type="text" value={license} onChange={e => setLicense(e.target.value)} placeholder="MIT" />
            </label>
            <label><span>Built with (model)</span>
              <input type="text" value={model} onChange={e => setModel(e.target.value)} placeholder="Claude Opus 4.1" />
            </label>
          </div>

          <label><span>Originating prompt (optional)</span>
            <textarea value={prompt} onChange={e => setPrompt(e.target.value)}
                      placeholder="Paste the prompt that produced this — others can rerun it as a starting point." />
          </label>

          <div className="legal">
            <b style={{ color: "var(--yellow)", fontWeight: 400 }}>By publishing</b> you confirm you have the right to
            share this link, the repo is public, and the project carries a real license. d4not library indexes,
            and <b style={{ color: "var(--red)" }}>makes no warranty</b> about the code behind the link.
          </div>

          {errMsg && <div className="error-msg on" style={{ marginTop: 10 }}>{errMsg}</div>}
        </div>
        )}
        <div className="footer">
          <span>Live immediately · trust upgrade later</span>
          {state === "done" ? (
            <button className="btn primary" onClick={() => { reset(); onClose(); }}>Close</button>
          ) : (
            <button className="btn primary" onClick={submit} disabled={state === "submitting"}>
              {state === "submitting" ? "Publishing…" : "Publish now"}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

function SafetyModal({ open, onClose }) {
  return (
    <div className={"modal-scrim" + (open ? " on" : "")} onClick={onClose}>
      <div className="modal safe-modal" onClick={e => e.stopPropagation()}>
        <div className="head">
          <h3>How d4not library reviews</h3>
          <span className="x" onClick={onClose}>close ✕</span>
        </div>
        <div className="body">
          <p className="intro">
            d4not library is an <b>index</b>, not a registry. We don't host code — every link points you to the
            author's repo on their platform. That means speed and transparency, but it also means responsibility
            is shared. Here's how we work:
          </p>
          <ul>
            <li><b style={{ color: "var(--lime)" }}>Reviewed</b> — a d4not maintainer cloned the repo, read the code, and signed it off.</li>
            <li><b style={{ color: "var(--yellow)" }}>Automated scan</b> — dependencies audited against known-CVE databases. No human review yet.</li>
            <li><b style={{ color: "var(--red)" }}>Unverified</b> — submitted but not yet checked. Treat exactly like any random repo on the internet.</li>
          </ul>
          <p className="intro" style={{ marginTop: 8 }}>
            <b style={{ color: "var(--red)" }}>d4not library assumes no liability</b> for code you run from linked
            repositories. Review the source, understand what it does, and only run it if you trust it. Report
            anything suspicious — we remove bad actors on sight.
          </p>
          <div className="sig">— signed, d4not</div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Catalog, DetailDrawer, SubmitModal, SafetyModal });
