// ---------- HarborDock app root ----------

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "harbor",
  "density": "comfortable",
  "showLandingFirst": true,
  "marketingPalette": "paper"
}/*EDITMODE-END*/;

const MARKETING_ROUTE_IDS = ["landing", "product", "workflow", "studios", "pricing", "journal", "not-found"];
const APP_ROUTE_IDS = ["dashboard", "projects", "clients", "calendar", "apps", "uploads", "inbox", "settings", "portal", "project-detail"];
const KNOWN_ROUTE_IDS = new Set([...MARKETING_ROUTE_IDS, ...APP_ROUTE_IDS, "signup"]);

function findPortalClientId(id) {
  if (!id) return null;
  const found = Object.entries(HD.portalAccess || {}).find(([cid, access]) =>
    access.slug === id || access.token === id || cid === id
  );
  return found ? found[0] : null;
}

function parseRouteIdentifier(raw) {
  if (!raw) return null;
  // Public portal hash: p/{slug-or-token}
  if (raw.startsWith("p/")) {
    const id = raw.slice(2);
    return { route: "public-portal", clientId: findPortalClientId(id), portalId: id };
  }
  if (raw === "signup") return { route: "signup" };
  if (!KNOWN_ROUTE_IDS.has(raw)) return { route: "not-found" };
  // Otherwise treat as a normal app route
  return { route: raw };
}

// Parse #/segment/value, #segment, or refresh-safe pathnames such as /dashboard.
function parseLocation() {
  const rawPath = (window.location.pathname || "")
    .replace(/^\/+|\/+$/g, "")
    .replace(/\/index\.html$/i, "");
  const pathRoute = parseRouteIdentifier(rawPath.toLowerCase() === "index.html" ? "" : rawPath);
  if (pathRoute) return pathRoute;

  const rawHash = (window.location.hash || "").replace(/^#\/?/, "");
  const hashRoute = parseRouteIdentifier(rawHash);
  if (hashRoute) return hashRoute;

  return { route: "landing" };
}

function App() {
  const [route, setRoute] = React.useState(() => {
    const parsed = parseLocation();
    if (parsed?.route === "public-portal") return "public-portal";
    if (parsed?.route === "signup") return "signup";
    return parsed?.route || "landing";
  });
  const [publicPortalClientId, setPublicPortalClientId] = React.useState(() => {
    const parsed = parseLocation();
    return parsed?.route === "public-portal" ? parsed.clientId : "sarkis";
  });
  const [previewPortalClientId, setPreviewPortalClientId] = React.useState("sarkis");
  const [openedProjectId, setOpenedProjectId] = React.useState(null);
  const [tweaks, setTweaks] = React.useState(TWEAK_DEFAULTS);
  const [tweaksOpen, setTweaksOpen] = React.useState(false);
  const [mobileNavOpen, setMobileNavOpen] = React.useState(false);
  const [searchOpen, setSearchOpen] = React.useState(false);
  const [notifOpen, setNotifOpen] = React.useState(false);
  const [newProjectOpen, setNewProjectOpen] = React.useState(false);
  const [shareClientId, setShareClientId] = React.useState(null); // open SharePortalModal for this client

  // Listen to hash changes (back/forward + manual)
  React.useEffect(() => {
    const onHash = () => {
      const parsed = parseLocation();
      if (!parsed) {
        setRoute("landing");
        return;
      }
      if (parsed.route === "public-portal") {
        setPublicPortalClientId(parsed.clientId);
        setRoute("public-portal");
        return;
      }
      setRoute(parsed.route);
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  // Global keybindings + overlay event bus
  React.useEffect(() => {
    const onKey = (e) => {
      const meta = e.metaKey || e.ctrlKey;
      if (meta && e.key.toLowerCase() === "k") {
        e.preventDefault();
        setSearchOpen(true);
      }
    };
    const onOpenSearch = () => setSearchOpen(true);
    const onOpenNotif = () => setNotifOpen(true);
    const onOpenNewProj = () => setNewProjectOpen(true);
    const onOpenShare = (e) => setShareClientId(e.detail?.clientId || "sarkis");
    const onPreviewPortal = (e) => {
      setPreviewPortalClientId(e.detail?.clientId || "sarkis");
      setOpenedProjectId(null);
      setRoute("portal");
      window.scrollTo({ top: 0, behavior: "instant" });
    };
    window.addEventListener("keydown", onKey);
    window.addEventListener("hd-open-search", onOpenSearch);
    window.addEventListener("hd-open-notifications", onOpenNotif);
    window.addEventListener("hd-open-new-project", onOpenNewProj);
    window.addEventListener("hd-share-portal", onOpenShare);
    window.addEventListener("hd-preview-portal", onPreviewPortal);
    return () => {
      window.removeEventListener("keydown", onKey);
      window.removeEventListener("hd-open-search", onOpenSearch);
      window.removeEventListener("hd-open-notifications", onOpenNotif);
      window.removeEventListener("hd-open-new-project", onOpenNewProj);
      window.removeEventListener("hd-share-portal", onOpenShare);
      window.removeEventListener("hd-preview-portal", onPreviewPortal);
    };
  }, []);

  // Tweaks host protocol
  React.useEffect(() => {
    const handler = (e) => {
      if (!e.data || typeof e.data !== "object") return;
      if (e.data.type === "__activate_edit_mode") setTweaksOpen(true);
      else if (e.data.type === "__deactivate_edit_mode") setTweaksOpen(false);
    };
    window.addEventListener("message", handler);
    window.parent.postMessage({ type: "__edit_mode_available" }, "*");
    return () => window.removeEventListener("message", handler);
  }, []);

  // Tweaks-panel quick jump
  React.useEffect(() => {
    const onJump = (e) => {
      const target = e.detail;
      if (target === "project-detail") {
        setOpenedProjectId("sarkis-cambridge");
        setRoute("project-detail");
      } else if (target === "public-portal") {
        setPublicPortalClientId("sarkis");
        window.location.hash = "#/p/sarkis-cambridge";
        setRoute("public-portal");
      } else {
        setOpenedProjectId(null);
        setRoute(target);
      }
      window.scrollTo({ top: 0, behavior: "instant" });
    };
    window.addEventListener("hd-navigate", onJump);
    return () => window.removeEventListener("hd-navigate", onJump);
  }, []);

  const setTweak = (keyOrObj, value) => {
    const edits = typeof keyOrObj === "string" ? { [keyOrObj]: value } : keyOrObj;
    setTweaks(prev => ({ ...prev, ...edits }));
    window.parent.postMessage({ type: "__edit_mode_set_keys", edits }, "*");
  };

  // Apply accent color globally via CSS variable
  React.useEffect(() => {
    const accentMap = {
      harbor:  { primary: "#1D4ED8", primary2: "#2563EB" },
      teal:    { primary: "#0F766E", primary2: "#14B8A6" },
      ink:     { primary: "#232628", primary2: "#2E3136" },
      lavender:{ primary: "#7C3AED", primary2: "#8B5CF6" },
    };
    const a = accentMap[tweaks.accent] || accentMap.harbor;
    document.documentElement.style.setProperty("--harbor", a.primary);
    document.documentElement.style.setProperty("--harbor-2", a.primary2);
  }, [tweaks.accent]);

  // Marketing palette
  React.useEffect(() => {
    const paletteMap = {
      paper: { paper: "#FAF8F4", sandSoft: "#F4F1EC" },
      bone:  { paper: "#F2EEE6", sandSoft: "#E8E2DA" },
      pearl: { paper: "#FFFFFF", sandSoft: "#F5F5F4" },
    };
    const p = paletteMap[tweaks.marketingPalette] || paletteMap.paper;
    document.documentElement.style.setProperty("--paper", p.paper);
    document.documentElement.style.setProperty("--sand-soft", p.sandSoft);
  }, [tweaks.marketingPalette]);

  const navigate = (id) => {
    setOpenedProjectId(null);
    setRoute(id);
    setMobileNavOpen(false);
    // Clear public portal hash if leaving
    if (window.location.hash && window.location.hash.startsWith("#/p/")) {
      history.replaceState(null, "", window.location.pathname);
    }
    window.scrollTo({ top: 0, behavior: "instant" });
  };

  const openProject = (id) => {
    setOpenedProjectId(id);
    setRoute("project-detail");
    setMobileNavOpen(false);
    window.scrollTo({ top: 0, behavior: "instant" });
  };

  // Public portal: no chrome, no shell, no nav
  if (route === "public-portal") {
    return (
      <>
        <PortalPage
          key={`public-${publicPortalClientId}`}
          isPublic
          clientId={publicPortalClientId}
          requirePasscode
        />
        <Toaster />
        <SupabaseStatus />
      </>
    );
  }

  // Signup flow: no chrome
  if (route === "signup") {
    return (
      <>
        <SignupPage
          onComplete={() => navigate("dashboard")}
          onBackToLanding={() => navigate("landing")}
        />
        <Toaster />
        <SupabaseStatus />
      </>
    );
  }

  // Marketing routes (light, no app shell)
  if (MARKETING_ROUTE_IDS.includes(route)) {
    return (
      <>
        {route === "landing"  && <LandingPage onEnterApp={() => navigate("dashboard")} onSignup={() => navigate("signup")} accent={tweaks.accent} onNav={navigate} />}
        {route === "product"  && <ProductPage onNav={navigate} onEnterApp={() => navigate("dashboard")} />}
        {route === "workflow" && <WorkflowPage onNav={navigate} onEnterApp={() => navigate("dashboard")} />}
        {route === "studios"  && <StudiosPage onNav={navigate} onEnterApp={() => navigate("dashboard")} />}
        {route === "pricing"  && <PricingPage onNav={navigate} onEnterApp={() => navigate("dashboard")} />}
        {route === "journal"  && <JournalPage onNav={navigate} onEnterApp={() => navigate("dashboard")} />}
        {route === "not-found" && <NotFoundPage onNav={navigate} />}
        <Toaster />
        <SupabaseStatus />
        {tweaksOpen && <HDTweaksPanel tweaks={tweaks} setTweak={setTweak} onClose={() => { setTweaksOpen(false); window.parent.postMessage({ type: "__edit_mode_dismissed" }, "*"); }} />}
      </>
    );
  }

  // Otherwise: app shell with sidebar
  return (
    <div style={{ display: "flex", minHeight: "100vh", background: "var(--ink)" }}>
      <Sidebar
        route={route === "project-detail" ? "projects" : route}
        onNavigate={navigate}
        mobileOpen={mobileNavOpen}
        onCloseMobile={() => setMobileNavOpen(false)}
      />
      <div style={{ flex: 1, minWidth: 0 }}>
        {route === "dashboard" && <DashboardPage onNavigate={navigate} onOpenProject={openProject} onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "projects" && <ProjectsPage onOpenProject={openProject} onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "project-detail" && <ProjectDetailPage projectId={openedProjectId} onBack={() => navigate("projects")} onNavigate={navigate} onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "clients" && <ClientsPage onOpenProject={openProject} onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "calendar" && <CalendarPage onOpenProject={openProject} onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "apps" && <AppsPage onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "uploads" && <StubPage title="Uploads inbox" body="A centralized view of every client upload, across every active project." iconName="Upload" onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "inbox" && <StubPage title="Studio inbox" body="Threaded conversations across all projects and clients — like email, but in context." iconName="Inbox" onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "settings" && <StubPage title="Workspace settings" body="Workspace, billing, team, and integrations — coming in Phase 2." iconName="Settings" onOpenMobileMenu={() => setMobileNavOpen(true)} />}
        {route === "portal" && <PortalPage key={`preview-${previewPortalClientId}`} onBackToStudio={() => navigate("dashboard")} clientId={previewPortalClientId} />}
      </div>
      <Toaster />
      {searchOpen && <CommandPalette onClose={() => setSearchOpen(false)} onNavigate={navigate} onOpenProject={openProject} />}
      {notifOpen && <NotificationsSheet onClose={() => setNotifOpen(false)} onOpenProject={openProject} />}
      {newProjectOpen && <NewProjectModal onClose={() => setNewProjectOpen(false)} />}
      {shareClientId && <SharePortalModal clientId={shareClientId} onClose={() => setShareClientId(null)} onPreviewPortal={(cid) => { setPreviewPortalClientId(cid); setRoute("portal"); }} />}
      {tweaksOpen && <HDTweaksPanel tweaks={tweaks} setTweak={setTweak} onClose={() => { setTweaksOpen(false); window.parent.postMessage({ type: "__edit_mode_dismissed" }, "*"); }} />}
      <SupabaseStatus />
    </div>
  );
}

const NotFoundPage = ({ onNav }) => (
  <div className="light-scroll" style={{ minHeight: "100vh", background: "var(--paper)", color: "var(--ink)", display: "flex", alignItems: "center", justifyContent: "center", padding: 24 }}>
    <main style={{ maxWidth: 520, width: "100%", textAlign: "center" }}>
      <HDLockup light markSize={34} />
      <div className="micro" style={{ marginTop: 36, color: "rgba(8,12,16,0.45)" }}>404</div>
      <h1 className="serif" style={{ fontSize: 44, lineHeight: 1.08, fontWeight: 500, margin: "10px 0 14px", letterSpacing: "-0.02em" }}>
        This HarborDock page is not available.
      </h1>
      <p style={{ fontSize: 14.5, lineHeight: 1.65, margin: "0 auto", color: "rgba(8,12,16,0.62)", maxWidth: 430 }}>
        The route may be mistyped, expired, or no longer published.
      </p>
      <div style={{ marginTop: 26, display: "flex", justifyContent: "center", gap: 10, flexWrap: "wrap" }}>
        <Button variant="secondary" light size="md" onClick={() => onNav("landing")}>Back home</Button>
        <Button variant="primary" size="md" onClick={() => onNav("dashboard")}>Open dashboard</Button>
      </div>
    </main>
  </div>
);

const SupabaseStatus = () => {
  const [state, setState] = React.useState(() => window.HDSupabase || { status: "idle" });

  React.useEffect(() => {
    const onReady = (event) => setState(event.detail || window.HDSupabase);
    window.addEventListener("hd-supabase-ready", onReady);
    return () => window.removeEventListener("hd-supabase-ready", onReady);
  }, []);

  if (!state || state.status === "idle") return null;

  const isError = state.status === "error";
  const label = state.status === "ready" ? "Supabase connected" : state.status === "connecting" ? "Connecting Supabase" : "Supabase unavailable";

  return (
    <div
      className="hd-supabase-status"
      role={isError ? "alert" : "status"}
      aria-live="polite"
      style={{
        position: "fixed",
        left: 16,
        bottom: 16,
        zIndex: 60,
        display: "inline-flex",
        alignItems: "center",
        gap: 8,
        maxWidth: "calc(100vw - 32px)",
        padding: "8px 10px",
        borderRadius: 8,
        background: isError ? "rgba(245,158,11,0.14)" : "rgba(29,78,216,0.14)",
        border: isError ? "1px solid rgba(245,158,11,0.34)" : "1px solid rgba(29,78,216,0.34)",
        color: isError ? "#FBD487" : "#9CC1FF",
        fontSize: 11.5,
        fontWeight: 500,
        boxShadow: "0 16px 40px -24px rgba(0,0,0,0.45)",
      }}
    >
      <span
        className={state.status === "connecting" ? "hd-pulse" : ""}
        style={{
          width: 7,
          height: 7,
          borderRadius: 99,
          background: isError ? "#F59E0B" : "var(--harbor-2)",
          flexShrink: 0,
        }}
      />
      <span style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
        {label}
      </span>
    </div>
  );
};

const StubPage = ({ title, body, iconName, onOpenMobileMenu }) => {
  const IconComp = window.Icon[iconName];
  return (
    <div>
      <Topbar eyebrow="WORKSPACE" title={title} onOpenMobileMenu={onOpenMobileMenu} />
      <div style={{ padding: "80px 32px", display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div style={{ maxWidth: 460, textAlign: "center" }}>
          <div style={{
            width: 64, height: 64, borderRadius: 16, margin: "0 auto 24px",
            background: "rgba(29,78,216,0.10)", border: "1px solid rgba(29,78,216,0.24)",
            color: "var(--harbor-2)",
            display: "flex", alignItems: "center", justifyContent: "center",
          }}><IconComp size={26} /></div>
          <h2 className="serif" style={{ fontSize: 32, letterSpacing: "-0.015em", fontWeight: 500, margin: 0 }}>
            {title}
          </h2>
          <p style={{ fontSize: 14.5, color: "var(--warm-gray)", marginTop: 12, lineHeight: 1.55 }}>{body}</p>
          <div style={{ marginTop: 24, display: "inline-flex", gap: 8 }}>
            <Button variant="primary" size="md" icon={<window.Icon.Plus size={13} />}>Coming Phase 2</Button>
          </div>
        </div>
      </div>
    </div>
  );
};

// ---------- Tweaks panel ----------
function HDTweaksPanel({ tweaks, setTweak, onClose }) {
  return (
    <div style={{
      position: "fixed", right: 20, top: 20, zIndex: 50,
      width: 300, background: "var(--charcoal)",
      border: "1px solid rgba(255,255,255,0.08)",
      borderRadius: 14, boxShadow: "0 24px 48px -16px rgba(0,0,0,0.4)",
      overflow: "hidden", color: "var(--white)",
      fontFamily: "var(--sans)",
    }}>
      <div style={{
        display: "flex", justifyContent: "space-between", alignItems: "center",
        padding: "14px 16px", borderBottom: "1px solid rgba(255,255,255,0.06)",
      }}>
        <div>
          <div className="micro" style={{ color: "var(--warm-gray)", fontSize: 9 }}>HARBORDOCK</div>
          <div style={{ fontSize: 13, fontWeight: 600, marginTop: 2 }}>Tweaks</div>
        </div>
        <button onClick={onClose} style={{
          background: "transparent", border: "none", color: "var(--warm-gray)",
          cursor: "pointer", padding: 4,
        }}><window.Icon.X size={14} /></button>
      </div>

      <div style={{ padding: 16, display: "flex", flexDirection: "column", gap: 20 }}>
        <TweakGroup label="Accent">
          <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 8 }}>
            {[
              { id: "harbor", color: "#1D4ED8", name: "Harbor" },
              { id: "teal", color: "#14B8A6", name: "Teal" },
              { id: "ink", color: "#2E3136", name: "Ink" },
              { id: "lavender", color: "#8B5CF6", name: "Lavender" },
            ].map(c => (
              <button
                key={c.id}
                onClick={() => setTweak("accent", c.id)}
                title={c.name}
                style={{
                  aspectRatio: 1, borderRadius: 8,
                  background: c.color,
                  border: tweaks.accent === c.id ? "2px solid white" : "2px solid transparent",
                  boxShadow: tweaks.accent === c.id ? "0 0 0 2px var(--charcoal), 0 0 0 3px var(--harbor)" : "none",
                  cursor: "pointer",
                }}
              />
            ))}
          </div>
        </TweakGroup>

        <TweakGroup label="Marketing palette">
          <div style={{ display: "flex", gap: 6 }}>
            {[
              { id: "paper", name: "Paper" },
              { id: "bone", name: "Bone" },
              { id: "pearl", name: "Pearl" },
            ].map(p => (
              <button
                key={p.id}
                onClick={() => setTweak("marketingPalette", p.id)}
                style={{
                  flex: 1, padding: "8px 10px", borderRadius: 7, cursor: "pointer",
                  background: tweaks.marketingPalette === p.id ? "rgba(29,78,216,0.14)" : "rgba(255,255,255,0.03)",
                  border: tweaks.marketingPalette === p.id ? "1px solid rgba(29,78,216,0.32)" : "1px solid rgba(255,255,255,0.06)",
                  color: tweaks.marketingPalette === p.id ? "#9CC1FF" : "var(--white)",
                  fontSize: 11.5, fontFamily: "var(--sans)", fontWeight: 500,
                }}>{p.name}</button>
            ))}
          </div>
        </TweakGroup>

        <TweakGroup label="Quick jump">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
            {[
              { id: "landing", label: "Landing" },
              { id: "signup", label: "Signup" },
              { id: "dashboard", label: "Dashboard" },
              { id: "projects", label: "Projects" },
              { id: "project-detail", label: "Project" },
              { id: "clients", label: "Clients" },
              { id: "apps", label: "Apps" },
              { id: "portal", label: "Portal (preview)" },
              { id: "public-portal", label: "Public portal" },
            ].map(j => (
              <button
                key={j.id}
                onClick={() => {
                  window.dispatchEvent(new CustomEvent("hd-navigate", { detail: j.id }));
                }}
                style={{
                  padding: "6px 8px", borderRadius: 6, cursor: "pointer",
                  background: "rgba(255,255,255,0.03)",
                  border: "1px solid rgba(255,255,255,0.06)",
                  color: "var(--white)", fontSize: 11.5, fontFamily: "var(--sans)",
                }}>{j.label}</button>
            ))}
          </div>
        </TweakGroup>

        <div style={{ fontSize: 11, color: "var(--warm-gray)", lineHeight: 1.55 }}>
          Accent rewrites the primary brand color across studio surfaces.
          Public portal opens at <span className="mono" style={{ color: "var(--white)" }}>#/p/sarkis-cambridge</span> — no login required.
        </div>
      </div>
    </div>
  );
}

const TweakGroup = ({ label, children }) => (
  <div>
    <div className="micro" style={{ color: "var(--warm-gray)", marginBottom: 8, fontSize: 9 }}>{label}</div>
    {children}
  </div>
);

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