/* global React, ReactDOM, PRShell, PRViews, PRPassport, PRDash, PRModal, PRUsers */
const { useState, useEffect, useRef, useMemo } = React;
const { Sidebar, Topbar, PageHead } = PRShell;
const { TableView, KanbanView, CardsView } = PRViews;
const { PassportView } = PRPassport;
const { DashboardView } = PRDash;
const { ModalRouter } = PRModal;
const { UsersView } = PRUsers;

const PAGE_META = {
  registry:  { title: "Registry",          sub: "Single source of truth for every R&D hypothesis. Lives free of procurement until handed off at Scale.", crumbs: ["Workspace", "Registry"] },
  kanban:    { title: "Pipeline",          sub: "Hypotheses by funnel stage. Advance a card when the gate criteria are met.", crumbs: ["Workspace", "Pipeline"] },
  cards:     { title: "Cards",             sub: "Grid view, optimised for scanning core-loops at a glance.", crumbs: ["Workspace", "Cards"] },
  dashboard: { title: "Dashboard",         sub: "Health of the pipeline: throughput, conversion, decision velocity.", crumbs: ["Workspace", "Dashboard"] },
  passport:  { title: "R&D Passport",      sub: "Full record of a hypothesis — what travels into procurement on Scale.", crumbs: ["Workspace", "Registry", "Passport"] },
  decision:  { title: "Awaiting decision", sub: "Hypotheses that finished Cold Test and need a Kill / Pivot / Scale call.", crumbs: ["Views", "Awaiting decision"] },
  scaled:    { title: "Scaled",            sub: "Handed off to production. Soft-launch tracking lives elsewhere.", crumbs: ["Views", "Scaled"] },
  archive:   { title: "Archive",           sub: "Killed hypotheses. Searchable so the same idea isn't tested twice.", crumbs: ["Views", "Archive"] },
  users:     { title: "Users & roles",     sub: "Manage team members, assign roles and permissions.", crumbs: ["Admin", "Users & roles"] },
};

// ── API helpers ───────────────────────────────────────────────────────────────

async function apiFetch(url, opts = {}) {
  const resp = await fetch(url, { headers: { "Content-Type": "application/json" }, ...opts });
  if (resp.status === 401) { window.location.href = "/login"; throw new Error("Unauthorized"); }
  return resp;
}

// ── Hash routing ──────────────────────────────────────────────────────────────

function parseHash() {
  const hash = window.location.hash.replace(/^#\/?/, "");
  const parts = hash.split("/").filter(Boolean);
  if (!parts.length) return { section: "registry", id: null };
  return { section: parts[0], id: parts[1] || null };
}

// ── Overlay panel ─────────────────────────────────────────────────────────────

function OverlayPanel({ openId, data, user, onClose, onDecide, onAdvance, onRefresh }) {
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    if (openId) {
      // Next frame so CSS transition fires
      requestAnimationFrame(() => setVisible(true));
    } else {
      setVisible(false);
    }
  }, [openId]);

  useEffect(() => {
    if (!openId) return;
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [openId, onClose]);

  if (!openId) return null;

  return (
    <>
      <div className="overlay-scrim" onClick={onClose} />
      <div className={"overlay-panel" + (visible ? " open" : "")}>
        <div className="overlay-head">
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <button className="btn btn-ghost" style={{ padding: "0 8px", height: 26, fontSize: 12 }} onClick={onClose}>
              <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
              Close
            </button>
            <span style={{ fontSize: 12, color: "var(--text-3)", fontFamily: "Geist Mono, monospace" }}>{openId}</span>
          </div>
          <div style={{ display: "flex", gap: 6 }}>
            <button className="btn btn-ghost" style={{ height: 26, padding: "0 10px", fontSize: 12 }}
              onClick={() => { window.history.pushState(null, "", "#/passport/" + openId); window.location.reload(); }}>
              Open full page
              <svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M7 17L17 7M7 7h10v10"/></svg>
            </button>
          </div>
        </div>
        <div className="overlay-body">
          <PassportView
            data={data}
            hypothesisId={openId}
            user={user}
            onDecide={onDecide}
            onAdvance={onAdvance}
            onRefresh={onRefresh}
            embedded={true}
          />
        </div>
      </div>
    </>
  );
}

// ── App ───────────────────────────────────────────────────────────────────────

function App() {
  const [active, setActive]         = useState("registry");
  const [view, setView]             = useState("table");
  const [theme, setThemeState]      = useState(() => localStorage.getItem("theme") || "light");
  const [data, setData]             = useState(null);
  const [activity, setActivity]     = useState([]);
  const [user, setUser]             = useState(null);
  const [loading, setLoading]       = useState(true);
  const [modal, setModal]           = useState(null);
  const [passportId, setPassportId] = useState(null);
  const [openId, setOpenId]         = useState(null);
  const [filters, setFilters]       = useState({ set: "all", stage: "", genre: "", author: "", risk: "" });

  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
    localStorage.setItem("theme", theme);
  }, [theme]);

  // ── Hash routing ────────────────────────────────────────────────────────────

  const applyHash = () => {
    const { section, id } = parseHash();
    const sec = PAGE_META[section] ? section : "registry";
    setActive(sec);
    if (sec === "passport" && id) setPassportId(id);
    else if (sec !== "passport")  setPassportId(null);
  };

  useEffect(() => {
    applyHash();
    window.addEventListener("popstate", applyHash);
    return () => window.removeEventListener("popstate", applyHash);
  }, []);

  const navigate = (section, id = null) => {
    const hash = id ? `/${section}/${id}` : `/${section}`;
    window.history.pushState(null, "", "#" + hash);
    setActive(section);
    if (id) setPassportId(id);
    else    setPassportId(null);
  };

  // ── Auth + initial load ──────────────────────────────────────────────────

  useEffect(() => { bootstrap(); }, []);

  const bootstrap = async () => {
    try {
      const setup = await fetch("/api/setup/status");
      if (setup.ok) {
        const { initialized } = await setup.json();
        if (!initialized) { window.location.href = "/setup"; return; }
      }
      const me = await apiFetch("/api/auth/me");
      if (!me.ok) return;
      setUser(await me.json());
      await loadData();
    } finally {
      setLoading(false);
    }
  };

  const loadData = async () => {
    const [dataResp, actResp] = await Promise.all([
      apiFetch("/api/data"),
      apiFetch("/api/activity"),
    ]);
    if (dataResp.ok) setData(await dataResp.json());
    if (actResp.ok)  setActivity(await actResp.json());
  };

  const refresh = () => loadData();

  // ── Navigation ────────────────────────────────────────────────────────────

  const handleOpen = (id) => setOpenId(id);

  // ── Actions ───────────────────────────────────────────────────────────────

  const handleAdvance = async (rndId, notes) => {
    await apiFetch(`/api/hypotheses/${rndId}/advance`, {
      method: "POST",
      body: JSON.stringify({ notes: notes || null }),
    });
    refresh();
  };

  const handleMove = async (rndId, targetStage) => {
    await apiFetch(`/api/hypotheses/${rndId}/move`, {
      method: "POST",
      body: JSON.stringify({ stage: targetStage }),
    });
    refresh();
  };

  const handleDecide = (rndId) => setModal({ type: "decide", rndId });
  const handleEdit   = (rndId) => setModal({ type: "edit", rndId });

  const handleLogout = async () => {
    await fetch("/api/auth/logout", { method: "POST" });
    window.location.href = "/login";
  };

  // ── Filter logic ──────────────────────────────────────────────────────────

  const filteredData = useMemo(() => {
    if (!data) return null;
    let hyps = data.hypotheses;
    if (filters.set === "active") hyps = hyps.filter(h => !h.decision);
    if (filters.set === "mine")   hyps = hyps.filter(h => h.author === data._meta?.currentUserId);
    if (filters.stage)  hyps = hyps.filter(h => h.stage === filters.stage);
    if (filters.genre)  hyps = hyps.filter(h => h.tags.includes(filters.genre));
    if (filters.author) hyps = hyps.filter(h => h.author === filters.author);
    if (filters.risk)   hyps = hyps.filter(h => h.risk === filters.risk);
    return { ...data, hypotheses: hyps };
  }, [data, filters]);

  // ── Loading / guard ───────────────────────────────────────────────────────

  if (loading) {
    return (
      <div style={{ display: "flex", height: "100vh", alignItems: "center", justifyContent: "center", color: "var(--text-3)", fontFamily: "Geist, sans-serif" }}>
        Loading…
      </div>
    );
  }
  if (!data) return null;

  const meta = { ...(PAGE_META[active] || PAGE_META.registry) };

  const effectiveView =
    active === "registry"  ? view       :
    active === "kanban"    ? "kanban"   :
    active === "cards"     ? "cards"    :
    active === "dashboard" ? "dashboard":
    active === "passport"  ? "passport" :
    active === "archive"   ? "archive"  :
    active === "decision"  ? "decision" :
    active === "scaled"    ? "scaled"   :
    active === "users"     ? "users"    : "table";

  const fd = filteredData;

  // Section subsets applied after user filters
  const archiveData  = { ...fd, hypotheses: fd.hypotheses.filter(h => h.decision === "kill") };
  const scaledData   = { ...fd, hypotheses: fd.hypotheses.filter(h => h.decision === "scale") };
  const decisionData = { ...fd, hypotheses: fd.hypotheses.filter(h => h.stage === "decision" && !h.decision) };
  const dashData     = { ...fd, _activity: activity };

  if (active === "passport" && passportId) {
    meta.crumbs = ["Workspace", "Registry", passportId];
    meta.sub = `${passportId} · The full record of a hypothesis. This is what travels into procurement on Scale.`;
  }

  const filterOptions = {
    stages:  data.stages.map(s => ({ value: s.id, label: s.label })),
    genres:  data.tags.map(t => ({ value: t, label: t })),
    authors: data.authors.map(a => ({ value: a.id, label: a.name })),
    risks:   [{ value: "low", label: "Low" }, { value: "med", label: "Medium" }, { value: "high", label: "High" }],
  };

  const showFilters = ["registry", "kanban", "cards", "archive", "decision", "scaled"].includes(active);

  return (
    <div className="app">
      <Sidebar
        active={active}
        setActive={(id) => navigate(id)}
        theme={theme}
        setTheme={setThemeState}
        data={data}
        user={user}
        onLogout={handleLogout}
      />
      <main className="main">
        <Topbar crumbs={meta.crumbs} onNew={() => setModal({ type: "new" })} user={user} />
        {active !== "users" && (
          <PageHead
            title={meta.title}
            sub={meta.sub}
            view={active === "registry" ? view : undefined}
            setView={setView}
            filters={showFilters ? filters : undefined}
            setFilters={showFilters ? setFilters : undefined}
            filterOptions={showFilters ? filterOptions : undefined}
            currentUserId={data._meta?.currentUserId}
          />
        )}

        {effectiveView === "table"     && <TableView    data={fd}         onOpen={handleOpen} />}
        {effectiveView === "kanban"    && <KanbanView   data={fd}         onOpen={handleOpen} onNew={() => setModal({ type: "new" })} onMove={handleMove} />}
        {effectiveView === "cards"     && <CardsView    data={fd}         onOpen={handleOpen} />}
        {effectiveView === "dashboard" && <DashboardView data={dashData} onOpen={handleOpen} />}
        {effectiveView === "passport"  && (
          <PassportView
            data={data}
            hypothesisId={passportId}
            user={user}
            onDecide={handleDecide}
            onAdvance={handleAdvance}
            onRefresh={refresh}
          />
        )}
        {effectiveView === "archive"   && <TableView data={archiveData}  onOpen={handleOpen} />}
        {effectiveView === "scaled"    && <CardsView data={scaledData}   onOpen={handleOpen} />}
        {effectiveView === "decision"  && <TableView data={decisionData} onOpen={handleOpen} />}
        {effectiveView === "users"     && <UsersView data={data} />}
      </main>

      <OverlayPanel
        openId={openId}
        data={data}
        user={user}
        onClose={() => setOpenId(null)}
        onDecide={(rndId) => { setModal({ type: "decide", rndId }); }}
        onAdvance={handleAdvance}
        onRefresh={refresh}
      />

      {modal && (
        <ModalRouter
          modal={modal}
          data={data}
          user={user}
          onClose={() => setModal(null)}
          onSuccess={(newId) => {
            setModal(null);
            refresh();
            if (newId) setOpenId(newId);
          }}
        />
      )}
    </div>
  );
}

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