// Integrations + Settings

function IntegrationsPage() {
  const hub = window.useClearCast();
  const [tab, setTab] = React.useState("channels");
  const integrations = hub.data.integrations || [];
  const [selectedId, setSelectedId] = React.useState(integrations[0]?.id || "instagram");
  const [handleDraft, setHandleDraft] = React.useState("");
  const [integrationBusy, setIntegrationBusy] = React.useState("");
  const [connectingId, setConnectingId] = React.useState("");
  const providers = hub.data.integrationProviders || {};
  // Channels you can actually connect TODAY (real OAuth + a working publisher).
  // X included — its per-business OAuth2 connect + publisher shipped with #71.
  const LIVE_CONNECT = new Set(["facebook", "instagram", "youtube", "mastodon", "x"]);
  const providerLive = (id) => LIVE_CONNECT.has(id);
  const doConnect = async (id) => {
    // Instagram publishes through a Facebook Page. If Facebook is already
    // connected, attach Instagram FROM that Page (re-reads the linked IG account)
    // instead of forcing a second Facebook login that often grants no Page.
    if (id === "instagram") {
      const fb = integrations.find((i) => i.id === "facebook");
      if (fb && fb.connected) {
        setConnectingId(id);
        try { await hub.actions.linkInstagram(); }
        catch (error) { hub.toast(error.message || "Could not link Instagram from your Facebook Page"); }
        finally { setConnectingId(""); }
        return;
      }
      hub.toast("Connect your Facebook Page first — Instagram publishes through it.");
      return;
    }
    // Mastodon connects to the user's own instance, so ask which one first.
    if (id === "mastodon") {
      const instance = window.prompt("Which Mastodon server is your account on?\n(e.g. mastodon.social)", "mastodon.social");
      if (!instance || !instance.trim()) return;
      setConnectingId(id);
      try { await hub.actions.connectMastodon(instance.trim()); }
      catch (error) { hub.toast(error.message || "Could not connect"); }
      finally { setConnectingId(""); }
      return;
    }
    setConnectingId(id);
    try { await hub.actions.connectIntegration(id); }
    catch (error) { hub.toast(error.message || "Could not connect"); }
    finally { setConnectingId(""); }
  };
  React.useEffect(() => {
    if (!integrations.find((item) => item.id === selectedId) && integrations[0]) setSelectedId(integrations[0].id);
  }, [integrations, selectedId]);
  const selected = integrations.find((item) => item.id === selectedId) || integrations[0] || {};
  // Edit the handle locally; commit once on blur (not an API call + toast per keystroke).
  React.useEffect(() => { setHandleDraft(selected.handle || ""); }, [selectedId, selected.handle]);
  const commitHandle = () => { if ((handleDraft || "") !== (selected.handle || "")) hub.actions.updateIntegration(selected.id, { handle: handleDraft }); };
  const permissions = new Set(hub.data.currentPermissions || []);
  const canManage = permissions.has("manage_integrations");
  const connectedCount = integrations.filter((item) => item.connected).length;
  const readyCount = integrations.filter((item) => item.publishReady).length;
  const issueCount = integrations.filter((item) => item.connected && !item.publishReady).length;
  const contentTypes = ["feed", "reel", "story", "short"];
  const allScopes = ["publish_feed", "publish_reels", "publish_pages", "video_publish", "youtube.upload", "pins:write", "manage_comments", "read_insights", "tweet_write", "users_read"];
  const tokenLabel = (item) => item.tokenExpiresAt ? new Date(item.tokenExpiresAt).toLocaleDateString() : "No expiry";
  const statusPill = (item) => {
    if (!item.connected) return <span className="pill">Disconnected</span>;
    if (item.publishReady) return <span className="pill green"><span className="pill-dot"/>Ready</span>;
    if (item.status === "reauth") return <span className="pill warn"><span className="pill-dot"/>Re-auth</span>;
    return <span className="pill warn"><span className="pill-dot"/>Limited</span>;
  };
  const toggleScope = async (scope) => {
    if (integrationBusy) return;
    setIntegrationBusy(`scope-${scope}`);
    const active = selected.scopes || [];
    const next = active.includes(scope) ? active.filter((item) => item !== scope) : [...active, scope];
    try {
      await hub.actions.updateIntegration(selected.id, { scopes: next });
    } finally {
      setIntegrationBusy("");
    }
  };
  const toggleType = async (type) => {
    if (integrationBusy) return;
    setIntegrationBusy(`type-${type}`);
    const active = selected.supportedTypes || [];
    const next = active.includes(type) ? active.filter((item) => item !== type) : [...active, type];
    try {
      await hub.actions.updateIntegration(selected.id, { supportedTypes: next.length ? next : [type] });
    } finally {
      setIntegrationBusy("");
    }
  };
  const runIntegrationAction = async (kind) => {
    if (integrationBusy || !selected?.id) return;
    setIntegrationBusy(kind);
    try {
      if (kind === "sync") await hub.actions.syncIntegration(selected.id);
      if (kind === "toggle") await hub.actions.toggleIntegration(selected.id);
      if (kind === "reconnect") await hub.actions.reconnectIntegration(selected.id);
    } finally {
      setIntegrationBusy("");
    }
  };

  const tools = [
    { name: "Canva", desc: "Design straight from Canva into ClearCast", cat: "Design", icon: "▦", clr: "#00C4CC" },
    { name: "Figma", desc: "Pull frames as post mockups", cat: "Design", icon: "F", clr: "#F24E1E" },
    { name: "Google Drive", desc: "Sync media folders automatically", cat: "Storage", icon: "▲", clr: "#FBBC04" },
    { name: "Dropbox", desc: "Pull files into the media library", cat: "Storage", icon: "▢", clr: "#0061FF" },
    { name: "Slack", desc: "Approval pings + publish alerts", cat: "Notifications", icon: "✦", clr: "#4A154B" },
    { name: "Microsoft Teams", desc: "Workflow notifications", cat: "Notifications", icon: "T", clr: "#5059C9" },
    { name: "Shopify", desc: "Product tagging in posts", cat: "Commerce", icon: "S", clr: "#95BF47" },
    { name: "HubSpot", desc: "Pipe leads from Inbox to CRM", cat: "CRM", icon: "H", clr: "#FF7A59", connected: false },
    { name: "Zapier", desc: "1,000+ apps via automations", cat: "Automation", icon: "Z", clr: "#FF4F00" },
  ];

  return (
    <div className="page mobile-integrations-page">
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 18 }}>
        <div className="tabs">
          <button className={`tab ${tab === "channels" ? "active" : ""}`} onClick={() => setTab("channels")}>Social channels <span style={{ color: "var(--accent-2)", marginLeft: 4 }}>{connectedCount}</span></button>
          <button className={`tab ${tab === "tools" ? "active" : ""}`} onClick={() => setTab("tools")}>Tools & Apps</button>
          <button className={`tab ${tab === "readiness" ? "active" : ""}`} onClick={() => setTab("readiness")}>Publish readiness</button>
          <button className={`tab ${tab === "api" ? "active" : ""}`} onClick={() => setTab("api")}>Webhooks & API</button>
        </div>
        {tab !== "channels" && <button disabled={!canManage} onClick={() => setTab("channels")} className="btn btn-primary"><Icon.Plus width="14" height="14" /> Connect new</button>}
      </div>

      {tab === "channels" && <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1fr) 360px", gap: 16 }}>
        <div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(3, minmax(0, 1fr))", gap: 12, marginBottom: 14 }}>
            <div className="card"><div className="muted" style={{ fontSize: 12 }}>Connected</div><div style={{ fontSize: 26, fontWeight: 650 }}>{connectedCount}</div></div>
            <div className="card"><div className="muted" style={{ fontSize: 12 }}>Publish ready</div><div style={{ fontSize: 26, fontWeight: 650 }}>{readyCount}</div></div>
            <div className="card"><div className="muted" style={{ fontSize: 12 }}>Needs attention</div><div style={{ fontSize: 26, fontWeight: 650, color: issueCount ? "var(--warn)" : "var(--text)" }}>{issueCount}</div></div>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))", gap: 12 }}>
            {integrations.map((item) => (
              <div key={item.id} role="button" onClick={() => setSelectedId(item.id)} className="card" style={{ padding: 16, textAlign: "left", cursor: "pointer", borderColor: selected.id === item.id ? "rgba(20,184,138,0.45)" : "var(--border)" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                <PlatformIcon id={item.id} size={40} />
                <div style={{ flex: 1, lineHeight: 1.25, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600 }}>{item.name}</div>
                  <div style={{ fontSize: 12, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.connected ? item.handle : "Not connected"}</div>
                </div>
                {statusPill(item)}
              </div>
              {item.connected ? (
                <div style={{ display: "flex", justifyContent: "space-between", marginTop: 14, paddingTop: 14, borderTop: "1px solid var(--border)" }}>
                  <div><div className="muted" style={{ fontSize: 11 }}>Followers</div><div style={{ fontSize: 13, fontWeight: 600 }}>{(item.followers || 0).toLocaleString()}</div></div>
                  <div><div className="muted" style={{ fontSize: 11 }}>Token</div><div style={{ fontSize: 13, color: item.status === "reauth" ? "var(--warn)" : "var(--text)" }}>{tokenLabel(item)}</div></div>
                  <div><div className="muted" style={{ fontSize: 11 }}>Types</div><div style={{ fontSize: 13, fontWeight: 600 }}>{(item.supportedTypes || []).join(", ")}</div></div>
                </div>
              ) : (
                <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, marginTop: 14, paddingTop: 14, borderTop: "1px solid var(--border)" }}>
                  <span className="muted" style={{ fontSize: 11.5 }}>{providerLive(item.id) ? "Secure connect ready" : "Coming soon"}</span>
                  <button className="btn btn-primary btn-sm" disabled={!canManage || connectingId === item.id} onClick={(e) => { e.stopPropagation(); doConnect(item.id); }}>
                    <Icon.Plug width="13" height="13" /> {connectingId === item.id ? "Connecting…" : "Connect"}
                  </button>
                </div>
              )}
              </div>
            ))}
          </div>
        </div>

        <div className="card" style={{ position: "sticky", top: 88, alignSelf: "start" }}>
          <div className="card-h"><h3>{selected.name || "Channel"} settings</h3>{statusPill(selected)}</div>
          <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14 }}>
            <PlatformIcon id={selected.id} size={42} />
            <div style={{ minWidth: 0 }}>
              <div style={{ fontWeight: 650 }}>{selected.accountName || "No account connected"}</div>
              <div className="muted" style={{ fontSize: 12 }}>{selected.handle || "Connect to enable publishing"}</div>
            </div>
          </div>
          <div style={{ display: "grid", gap: 10, marginBottom: 14 }}>
            <label><div className="field-label">Display handle</div><input className="input" disabled={!canManage || !selected.connected} value={handleDraft} onChange={(event) => setHandleDraft(event.target.value)} onBlur={commitHandle} onKeyDown={(event) => { if (event.key === "Enter") event.target.blur(); }}/></label>
            {/* Status is REAL state (set by connect / sync / publish results) — the
                old dropdown let anyone hand-set a dead channel to "Healthy", wiping
                its issues and faking a green "Ready" that failed at publish time. */}
            <label><div className="field-label">Connection status</div><input className="input" disabled value={selected.status === "healthy" ? "Healthy" : selected.status === "reauth" ? "Needs re-auth" : selected.status === "limited" ? "Limited permissions" : selected.status === "choose_page" ? "Choose a Page" : "Disconnected"} readOnly /></label>
          </div>
          <div className="field-label">Supported post types</div>
          <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 14 }}>
            {contentTypes.map((type) => <button key={type} disabled={!canManage || !!integrationBusy} onClick={() => toggleType(type)} className={`btn btn-sm ${(selected.supportedTypes || []).includes(type) ? "btn-primary" : ""}`}>{integrationBusy === `type-${type}` ? "Saving..." : type}</button>)}
          </div>
          <div className="field-label">Scopes</div>
          <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 14 }}>
            {allScopes.map((scope) => <button key={scope} disabled={!canManage || !selected.connected || !!integrationBusy} onClick={() => toggleScope(scope)} className={`btn btn-sm ${(selected.scopes || []).includes(scope) ? "btn-primary" : ""}`}>{integrationBusy === `scope-${scope}` ? "Saving..." : scope}</button>)}
          </div>
          {Array.isArray(selected.pendingPageChoices) && selected.pendingPageChoices.length > 0 && (
            <div className="card" style={{ background: "rgba(240,101,63,0.08)", borderColor: "rgba(240,101,63,0.3)", marginBottom: 14 }}>
              <div style={{ fontSize: 13, fontWeight: 650 }}>Choose which Facebook Page to connect</div>
              <div className="muted" style={{ fontSize: 12, margin: "4px 0 10px" }}>This account manages multiple Pages. Pick the one for this business:</div>
              <div style={{ display: "grid", gap: 8 }}>
                {selected.pendingPageChoices.map((p) => (
                  <button key={p.id} className="btn" disabled={!!integrationBusy} style={{ justifyContent: "space-between", textAlign: "left" }}
                    onClick={async () => { setIntegrationBusy("pick-" + p.id); try { await hub.actions.selectFacebookPage(p.id); } catch (e) { hub.toast(e.message || "Could not connect that Page"); } finally { setIntegrationBusy(""); } }}>
                    <span>{integrationBusy === "pick-" + p.id ? "Connecting…" : p.name}</span>
                    {p.hasIg && <span className="faint" style={{ fontSize: 11 }}>{p.igUsername ? "@" + p.igUsername : "IG linked"}</span>}
                  </button>
                ))}
              </div>
            </div>
          )}
          {((selected.issues || []).length > 0 || selected.lastConnectError) && <div className="card" style={{ background: "rgba(245,158,11,0.08)", borderColor: "rgba(245,158,11,0.25)", marginBottom: 14 }}>
            <div style={{ fontSize: 13, fontWeight: 650, color: "var(--warn)" }}>Attention needed</div>
            {/* Full reason + fix from the last failed publish (lastConnectError), else the raw issues. */}
            {selected.lastConnectError
              ? <div className="muted" style={{ fontSize: 12, marginTop: 4 }}>{selected.lastConnectError}</div>
              : (selected.issues || []).map((issue) => <div key={issue} className="muted" style={{ fontSize: 12, marginTop: 4 }}>{issue}</div>)}
            <div className="muted" style={{ fontSize: 11.5, marginTop: 6, opacity: 0.8 }}>Reconnect below to clear this and resume publishing.</div>
          </div>}
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
            <button disabled={!canManage || !selected.connected || !!integrationBusy} onClick={() => runIntegrationAction("sync")} className="btn"><Icon.Refresh width="14" height="14" /> {integrationBusy === "sync" ? "Testing..." : "Test sync"}</button>
            <button disabled={!canManage || !!integrationBusy} onClick={() => selected.connected ? runIntegrationAction("toggle") : doConnect(selected.id)} className="btn">{integrationBusy === "toggle" ? "Saving..." : selected.connected ? "Disconnect" : "Connect"}</button>
            <button disabled={!canManage || !!integrationBusy} onClick={() => selected.connected ? runIntegrationAction("reconnect") : doConnect(selected.id)} className="btn btn-primary" style={{ gridColumn: "1 / -1" }}>{integrationBusy === "reconnect" ? "Authorizing..." : selected.connected ? "Reconnect / authorize" : "Connect account"}</button>
          </div>
        </div>
      </div>}

      {tab === "readiness" && <div className="card" style={{ padding: 0 }}>
        <div style={{ padding: "16px 20px", borderBottom: "1px solid var(--border)" }}>
          <div style={{ fontSize: 14, fontWeight: 650 }}>Publishing readiness</div>
          <div className="muted" style={{ fontSize: 12.5 }}>ClearCast checks connection health, scopes, token status, and supported post types before a post can be published.</div>
        </div>
        <table className="tbl">
          <thead><tr><th>Channel</th><th>Feed</th><th>Reel</th><th>Story</th><th>Short</th><th>Scopes</th><th>Status</th></tr></thead>
          <tbody>{integrations.map((item) => (
            <tr key={item.id}>
              <td><div style={{ display: "flex", alignItems: "center", gap: 8 }}><PlatformIcon id={item.id} size={24}/><b>{item.name}</b></div></td>
              {contentTypes.map((type) => <td key={type}>{(item.supportedTypes || []).includes(type) && item.publishReady ? <Icon.Check width="16" height="16" style={{ color: "var(--accent)" }}/> : <span className="muted">-</span>}</td>)}
              <td className="muted">{(item.scopes || []).length}</td>
              <td>{statusPill(item)}</td>
            </tr>
          ))}</tbody>
        </table>
      </div>}

      {tab === "tools" && <div>
        <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600, letterSpacing: "0.04em", textTransform: "uppercase", marginBottom: 12 }}>Tools & integrations</div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))", gap: 12 }}>
          {tools.map(t => (
            <div key={t.name} className="card" style={{ padding: 14 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ width: 40, height: 40, borderRadius: 8, background: `${t.clr}22`, color: t.clr, display: "grid", placeItems: "center", fontWeight: 800, fontSize: 16 }}>{t.icon}</div>
                <div style={{ flex: 1, lineHeight: 1.25 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                    <span style={{ fontSize: 13.5, fontWeight: 600 }}>{t.name}</span>
                    <span className="pill" style={{ padding: "1px 7px", fontSize: 10 }}>Coming soon</span>
                  </div>
                  <div style={{ fontSize: 11, color: "var(--text-3)" }}>{t.cat}</div>
                </div>
              </div>
              <div style={{ fontSize: 12, color: "var(--text-2)", marginTop: 10, lineHeight: 1.45 }}>{t.desc}</div>
              <button className="btn btn-sm" disabled style={{ marginTop: 12, width: "100%", justifyContent: "center" }} title="This integration isn't available yet">
                Coming soon
              </button>
            </div>
          ))}
        </div>
      </div>}

      {tab === "api" && <div className="card" style={{ padding: 28, textAlign: "center" }}>
        <div style={{ width: 44, height: 44, borderRadius: 11, background: "var(--elev)", display: "grid", placeItems: "center", margin: "0 auto 12px", color: "var(--accent-2)" }}>
          <Icon.Lock width="20" height="20" />
        </div>
        <div style={{ fontSize: 16, fontWeight: 700, marginBottom: 6 }}>Webhooks & API keys live in Developer</div>
        <div className="muted" style={{ fontSize: 13, maxWidth: 460, margin: "0 auto 16px", lineHeight: 1.6 }}>
          Generate API keys and register webhook endpoints (post.published, inbox.message, approval.updated and more) on the dedicated Developer page.
        </div>
        <button className="btn btn-primary" onClick={() => { window.location.hash = "developer"; }}>Open Developer / API</button>
      </div>}
    </div>
  );
}

function SettingsPage() {
  const [section, setSection] = React.useState("workspace");

  const sections = [
    { id: "workspace", label: "Workspace", ico: "Settings" },
    { id: "profile", label: "Profile", ico: "Users" },
    { id: "billing", label: "Billing & Plan", ico: "File" },
    { id: "notifications", label: "Notifications", ico: "Bell" },
    { id: "security", label: "Security", ico: "Lock" },
    { id: "publishing", label: "Publishing rules", ico: "Calendar" },
    { id: "ai", label: "AI assistant", ico: "Sparkles" },
    { id: "exports", label: "Exports & data", ico: "Download" },
  ];

  return (
    <div className="page mobile-settings-page" style={{ padding: 0 }}>
      <div style={{ display: "grid", gridTemplateColumns: "240px minmax(0, 1fr)", minHeight: "calc(100vh - 72px)" }}>
        <div style={{ borderRight: "1px solid var(--border)", padding: "20px 14px" }}>
          {sections.map(s => {
            const Ico = Icon[s.ico];
            const active = section === s.id;
            return (
              <button key={s.id} className={`nav-item ${active ? "active" : ""}`} onClick={() => setSection(s.id)}>
                <Ico className="ico" />
                <span>{s.label}</span>
              </button>
            );
          })}
        </div>

        <div style={{ padding: "28px 36px", maxWidth: 820 }}>
          {section === "workspace" && <WorkspaceSettings />}
          {section === "profile" && <ProfileSettings />}
          {section === "billing" && <BillingSettings />}
          {section === "notifications" && <NotificationSettings />}
          {section === "security" && <SecuritySettings />}
          {section === "publishing" && <PublishingSettings />}
          {section === "ai" && <AISettings />}
          {section === "exports" && <ExportsSettings />}
        </div>
      </div>
    </div>
  );
}

function SettingsHeader({ title, desc }) {
  return (
    <div style={{ marginBottom: 24 }}>
      <h2 style={{ margin: 0, fontSize: 22, fontWeight: 600, letterSpacing: "-0.015em" }}>{title}</h2>
      <p style={{ margin: "6px 0 0", color: "var(--text-3)", fontSize: 13 }}>{desc}</p>
    </div>
  );
}

function Row({ label, desc, children }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "260px 1fr", gap: 24, padding: "18px 0", borderTop: "1px solid var(--border)" }}>
      <div>
        <div style={{ fontSize: 13.5, fontWeight: 600 }}>{label}</div>
        {desc && <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 4, lineHeight: 1.5 }}>{desc}</div>}
      </div>
      <div>{children}</div>
    </div>
  );
}

function Toggle({ on, onChange }) {
  return (
    <button onClick={() => onChange && onChange(!on)} style={{ position: "relative", width: 36, height: 20, borderRadius: 999, background: on ? "var(--accent)" : "var(--elev)", border: "1px solid var(--border)", transition: "background .15s" }}>
      <span style={{ position: "absolute", top: 2, left: on ? 18 : 2, width: 14, height: 14, borderRadius: 999, background: "white", transition: "left .15s" }}/>
    </button>
  );
}

function WorkspaceSettings() {
  const hub = window.useClearCast();
  const workspace = hub?.data?.workspace || {};
  const [name, setName] = React.useState(workspace.name || "");
  const [timezone, setTimezone] = React.useState(workspace.timezone || "America/New_York");
  const [language, setLanguage] = React.useState(workspace.language || "English (US)");
  const [brandVoice, setBrandVoice] = React.useState(workspace.brandVoice || "");
  const [watermark, setWatermark] = React.useState(workspace.watermark !== false);
  const [logoDataUrl, setLogoDataUrl] = React.useState(workspace.logoDataUrl || "");
  const logoInputRef = React.useRef(null);
  const save = () => hub.actions.saveWorkspace({ name, timezone, language, brandVoice, watermark, logoDataUrl });
  const uploadLogo = (event) => {
    const file = event.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => setLogoDataUrl(reader.result);
    reader.readAsDataURL(file);
  };

  return (
    <>
      <SettingsHeader title="Workspace" desc="General settings for this business — applies to all team members." />
      <Row label="Workspace name" desc="Shown in invites and reports.">
        <input className="input" value={name} onChange={(event) => setName(event.target.value)} placeholder="Your business name" style={{ maxWidth: 360 }}/>
      </Row>
      <Row label="Logo" desc="Recommended 256×256 PNG.">
        <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
          <div className="brand-mark" style={{ width: 56, height: 56, fontSize: 22, borderRadius: 14, overflow: "hidden" }}>
            {logoDataUrl ? <img src={logoDataUrl} alt="Workspace logo" style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : <Icon.Image width="22" height="22" />}
          </div>
          <input ref={logoInputRef} type="file" accept="image/*" onChange={uploadLogo} style={{ display: "none" }} />
          <button className="btn" onClick={() => logoInputRef.current?.click()}>Upload new</button>
          <button className="btn btn-ghost" onClick={() => setLogoDataUrl("")}>Remove</button>
        </div>
      </Row>
      <Row label="Default timezone">
        <select className="select" value={timezone} onChange={(event) => setTimezone(event.target.value)} style={{ maxWidth: 360 }}>
          <option value="America/New_York">America/New_York (EDT)</option>
          <option value="America/Los_Angeles">America/Los_Angeles (PDT)</option>
          <option value="Europe/London">Europe/London (BST)</option>
          <option value="Asia/Tokyo">Asia/Tokyo (JST)</option>
        </select>
      </Row>
      <Row label="Default language">
        <select className="select" value={language} onChange={(event) => setLanguage(event.target.value)} style={{ maxWidth: 360 }}>
          <option>English (US)</option>
          <option>French</option>
          <option>Spanish</option>
          <option>Japanese</option>
        </select>
      </Row>
      <Row label="Brand voice" desc="The AI assistant uses this when drafting captions.">
        <textarea className="textarea" rows="3" value={brandVoice} onChange={(event) => setBrandVoice(event.target.value)} placeholder="Describe how your brand sounds — e.g. warm, concise, no corporate jargon." style={{ maxWidth: 480 }}/>
      </Row>
      <Row label="Watermark posts" desc="Adds a CC watermark to videos before publishing.">
        <Toggle on={watermark} onChange={setWatermark}/>
      </Row>
      <div className="settings-savebar">
        <div>
          <div style={{ fontSize: 13, fontWeight: 600 }}>Workspace changes</div>
          <div style={{ fontSize: 11.5, color: "var(--text-3)" }}>Save to keep these settings after refresh.</div>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          <button className="btn" onClick={() => {
            setName(workspace.name || "");
            setTimezone(workspace.timezone || "America/New_York");
            setLanguage(workspace.language || "English (US)");
            setBrandVoice(workspace.brandVoice || "");
            setWatermark(workspace.watermark !== false);
            setLogoDataUrl(workspace.logoDataUrl || "");
          }}>Cancel</button>
          <button className="btn btn-primary" onClick={save}>Save changes</button>
        </div>
      </div>
    </>
  );
}

function SettingsSaveBar({ title = "Settings changes", onSave, onReset }) {
  const [saving, setSaving] = React.useState(false);
  const runSave = async () => {
    if (saving) return;
    setSaving(true);
    try {
      await onSave?.();
    } finally {
      setSaving(false);
    }
  };
  return (
    <div className="settings-savebar">
      <div>
        <div style={{ fontSize: 13, fontWeight: 600 }}>{title}</div>
        <div style={{ fontSize: 11.5, color: "var(--text-3)" }}>Saved settings persist after refresh and feed the operating workflows.</div>
      </div>
      <div style={{ display: "flex", gap: 10 }}>
        {onReset && <button className="btn" disabled={saving} onClick={onReset}>Cancel</button>}
        <button className="btn btn-primary" disabled={saving} onClick={runSave}>{saving ? "Saving..." : "Save changes"}</button>
      </div>
    </div>
  );
}

function ProfileSettings() {
  const hub = window.useClearCast();
  const workspace = hub.data.workspace || {};
  const profile = workspace.profile || {};
  const authUser = hub.data.authUser || {};
  const seed = () => ({
    fullName: profile.fullName || authUser.name || authUser.email || "",
    email: profile.email || authUser.email || "",
    jobTitle: profile.jobTitle || "",
    workStart: profile.workStart || "09:00",
    workEnd: profile.workEnd || "18:00",
    avatarDataUrl: profile.avatarDataUrl || ""
  });
  const [form, setForm] = React.useState(seed);
  const avatarInputRef = React.useRef(null);
  const set = (key) => (event) => setForm((prev) => ({ ...prev, [key]: event.target.value }));
  const initials = (form.fullName || form.email || "?").trim().split(/\s+/).map((part) => part[0]).slice(0, 2).join("").toUpperCase() || "?";
  const uploadAvatar = (event) => {
    const file = event.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => setForm((prev) => ({ ...prev, avatarDataUrl: reader.result }));
    reader.readAsDataURL(file);
  };
  const save = () => hub.actions.saveWorkspace({ ...workspace, profile: form });

  return (
    <>
      <SettingsHeader title="Profile" desc="How you appear to your teammates." />
      <Row label="Avatar">
        <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
          <div className="avatar sz-48" style={{ background: "linear-gradient(135deg, #f4c2a1, #d99c70)", color: "#3a1f0c", overflow: "hidden" }}>
            {form.avatarDataUrl ? <img src={form.avatarDataUrl} alt="Avatar" style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : initials}
          </div>
          <input ref={avatarInputRef} type="file" accept="image/*" onChange={uploadAvatar} style={{ display: "none" }} />
          <button className="btn" onClick={() => avatarInputRef.current?.click()}>Upload</button>
          {form.avatarDataUrl && <button className="btn btn-ghost" onClick={() => setForm((prev) => ({ ...prev, avatarDataUrl: "" }))}>Remove</button>}
        </div>
      </Row>
      <Row label="Full name"><input className="input" value={form.fullName} onChange={set("fullName")} placeholder="Your name" style={{ maxWidth: 360 }}/></Row>
      <Row label="Email"><input className="input" value={form.email} onChange={set("email")} placeholder="you@example.com" style={{ maxWidth: 360 }}/></Row>
      <Row label="Job title"><input className="input" value={form.jobTitle} onChange={set("jobTitle")} placeholder="e.g. Head of Brand" style={{ maxWidth: 360 }}/></Row>
      <Row label="Working hours" desc="Used to set 'Best time' recommendations against your availability.">
        <div style={{ display: "flex", gap: 8 }}>
          <input className="input" type="time" value={form.workStart} onChange={set("workStart")} style={{ maxWidth: 120 }}/>
          <span style={{ alignSelf: "center", color: "var(--text-3)" }}>to</span>
          <input className="input" type="time" value={form.workEnd} onChange={set("workEnd")} style={{ maxWidth: 120 }}/>
        </div>
      </Row>
      <SettingsSaveBar title="Profile changes" onSave={save} onReset={() => setForm(seed())} />
    </>
  );
}

function BillingSettings() {
  const hub = window.useClearCast();
  const data = hub.data || {};
  const billing = data.billing || {};
  const plans = data.billingPlans || [];
  const current = plans.find((p) => p.id === (billing.plan || "free")) || { name: (billing.plan || "Free"), price: 0, blurb: "" };
  const connectedChannels = (data.integrations || []).filter((i) => i.connected).length;
  const businessCount = (data.workspaces || []).length || 1;
  const canceling = billing.status === "canceled" || billing.cancelAtPeriodEnd;
  const goBilling = () => (hub.setPage ? hub.setPage("billing") : (window.location.hash = "billing"));
  return (
    <>
      <SettingsHeader title="Billing & Plan" desc="A quick summary — full plan changes, the cost calculator, and invoices live on the Billing & Plan page." />
      <div className="card" style={{ padding: 20, background: "linear-gradient(135deg, rgba(20,184,138,0.08), transparent)", borderColor: "rgba(20,184,138,0.2)" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 12, flexWrap: "wrap" }}>
          <div>
            <div className={`pill ${canceling ? "warn" : "green"}`} style={{ marginBottom: 8 }}><span className="pill-dot"/>{canceling ? "Canceling at period end" : "Current plan"}</div>
            <div style={{ fontSize: 24, fontWeight: 600 }}>{current.name}{current.price ? <> — ${current.price}<span style={{ fontSize: 14, color: "var(--text-3)", fontWeight: 400 }}> / mo per business</span></> : <span style={{ fontSize: 14, color: "var(--text-3)", fontWeight: 400 }}> — free</span>}</div>
            <div style={{ fontSize: 12.5, color: "var(--text-3)", marginTop: 4 }}>{current.blurb}{billing.renewsAt ? ` · renews ${billing.renewsAt}` : ""}</div>
          </div>
          <button className="btn btn-primary" onClick={goBilling}>Manage plan</button>
        </div>
        <div className="divider"/>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 18 }}>
          <div><div style={{ fontSize: 11, color: "var(--text-3)" }}>Status</div><div style={{ fontSize: 16, fontWeight: 600 }}>{canceling ? "Canceling" : "Active"}</div></div>
          <div><div style={{ fontSize: 11, color: "var(--text-3)" }}>Businesses</div><div style={{ fontSize: 16, fontWeight: 600 }}>{businessCount}</div></div>
          <div><div style={{ fontSize: 11, color: "var(--text-3)" }}>Channels connected</div><div style={{ fontSize: 16, fontWeight: 600 }}>{connectedChannels}</div></div>
        </div>
      </div>

      <Row label="Invoices & payment method" desc="Receipts and your payment method are managed on the Billing & Plan page.">
        <button className="btn" onClick={goBilling}><Icon.External width="14" height="14" /> Open Billing &amp; Plan</button>
      </Row>
    </>
  );
}

function NotificationSettings() {
  const hub = window.useClearCast();
  const workspace = hub.data.workspace || {};
  const defaults = [
    { label: "Comments & DMs", desc: "New replies on your posts.", e: true, p: false, s: true },
    { label: "Approval requests", desc: "Someone tagged you for review.", e: true, p: true, s: true },
    { label: "Post failures", desc: "When a scheduled post fails to publish.", e: true, p: true, s: true },
    { label: "Performance milestones", desc: "A post crosses 10K reach.", e: false, p: true, s: false },
    { label: "Weekly digest", desc: "Mondays at 9 AM.", e: true, p: false, s: false },
    { label: "Team activity", desc: "When teammates leave comments on drafts.", e: false, p: false, s: true },
  ];
  const saved = workspace.notificationSettings || {};
  const build = () => defaults.map((item) => ({ ...item, ...(saved[item.label] || {}) }));
  const [groups, setGroups] = React.useState(build);
  React.useEffect(() => setGroups(build()), [JSON.stringify(saved)]);
  const setChannel = (label, key, value) => setGroups((current) => current.map((item) => item.label === label ? { ...item, [key]: value } : item));
  const save = () => hub.actions.saveWorkspace({
    ...workspace,
    notificationSettings: Object.fromEntries(groups.map((item) => [item.label, { e: item.e, p: item.p, s: item.s }]))
  });

  return (
    <>
      <SettingsHeader title="Notifications" desc="Pick which alerts reach you, and which Task Center alerts stay active." />
      <div style={{ display: "grid", gridTemplateColumns: "1fr 80px 80px 80px", padding: "0 0 14px", color: "var(--text-3)", fontSize: 11, fontWeight: 600, letterSpacing: "0.04em", textTransform: "uppercase", borderBottom: "1px solid var(--border)" }}>
        <div>Notification</div>
        <div style={{ textAlign: "center" }}>Email</div>
        <div style={{ textAlign: "center" }}>Push</div>
        <div style={{ textAlign: "center" }}>Slack</div>
      </div>
      {groups.map(g => (
        <div key={g.label} style={{ display: "grid", gridTemplateColumns: "1fr 80px 80px 80px", padding: "14px 0", borderTop: "1px solid var(--border)", alignItems: "center" }}>
          <div>
            <div style={{ fontSize: 13.5, fontWeight: 600 }}>{g.label}</div>
            <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 2 }}>{g.desc}</div>
          </div>
          <div style={{ textAlign: "center" }}><Toggle on={g.e} onChange={(value) => setChannel(g.label, "e", value)}/></div>
          <div style={{ textAlign: "center" }}><Toggle on={g.p} onChange={(value) => setChannel(g.label, "p", value)}/></div>
          <div style={{ textAlign: "center" }}><Toggle on={g.s} onChange={(value) => setChannel(g.label, "s", value)}/></div>
        </div>
      ))}
      <SettingsSaveBar title="Notification changes" onSave={save} onReset={() => setGroups(build())} />
    </>
  );
}

// Real personal two-factor (TOTP) enrollment wired to Supabase factors.
function TwoFactorManager() {
  const hub = window.useClearCast();
  const enabled = Boolean(hub.data && hub.data.mfaEnabled);
  // Authenticator (TOTP) enrollment requires a password to re-verify; Google/SSO
  // accounts have none, so they manage 2FA through their identity provider.
  const federated = Boolean(hub.data && hub.data.authProvider && hub.data.authProvider !== "password");
  const [open, setOpen] = React.useState(null); // "enable" | "disable" | null
  const [step, setStep] = React.useState("password");
  const [password, setPassword] = React.useState("");
  const [enroll, setEnroll] = React.useState(null);
  const [code, setCode] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");
  const close = () => { setOpen(null); setStep("password"); setPassword(""); setEnroll(null); setCode(""); setErr(""); setBusy(false); };

  const begin = async () => {
    setErr(""); setBusy(true);
    try { const r = await hub.actions.mfaBegin(password); setEnroll(r); setStep("scan"); }
    catch (e) { setErr(e.message || "Could not start setup"); } finally { setBusy(false); }
  };
  const activate = async () => {
    setErr(""); setBusy(true);
    try { await hub.actions.mfaActivate(password, enroll.factorId, code); close(); }
    catch (e) { setErr(e.message || "That code wasn't valid"); } finally { setBusy(false); }
  };
  const disable = async () => {
    setErr(""); setBusy(true);
    try { await hub.actions.mfaDisable(password); close(); }
    catch (e) { setErr(e.message || "Could not turn it off"); } finally { setBusy(false); }
  };

  return (
    <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
      <span className={`pill ${enabled ? "green" : "warn"}`}><span className="pill-dot"/>{enabled ? "On" : "Off"}</span>
      {federated
        ? <span className="muted" style={{ fontSize: 12.5 }}>You sign in with Google/SSO — manage two-factor through your identity provider.</span>
        : enabled
          ? <button className="btn btn-sm" onClick={() => setOpen("disable")}>Turn off</button>
          : <button className="btn btn-sm btn-primary" onClick={() => setOpen("enable")}>Enable</button>}

      {open && (
        <div className="modal-overlay" onClick={close} style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.6)", display: "grid", placeItems: "center", zIndex: 1000 }}>
          <div className="card" onClick={(e) => e.stopPropagation()} style={{ width: 400, maxWidth: "92vw", padding: 22 }}>
            {open === "enable" && step === "password" && <>
              <h3 style={{ marginTop: 0 }}>Enable two-factor</h3>
              <p className="muted" style={{ fontSize: 13 }}>Confirm your password to begin.</p>
              <input className="input" type="password" placeholder="Current password" value={password} onChange={(e) => setPassword(e.target.value)} autoFocus style={{ marginBottom: 10 }} />
              {err && <div style={{ color: "var(--danger)", fontSize: 12.5, marginBottom: 10 }}>{err}</div>}
              <div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
                <button className="btn" onClick={close}>Cancel</button>
                <button className="btn btn-primary" disabled={busy || !password} onClick={begin}>{busy ? "…" : "Continue"}</button>
              </div>
            </>}
            {open === "enable" && step === "scan" && enroll && <>
              <h3 style={{ marginTop: 0 }}>Scan with your authenticator</h3>
              <p className="muted" style={{ fontSize: 13 }}>Scan this QR in Google Authenticator, 1Password, Authy, etc. — then enter the 6-digit code.</p>
              {enroll.qrCode && <div style={{ background: "#fff", padding: 10, borderRadius: 10, width: 180, margin: "0 auto 12px" }}><img src={enroll.qrCode} alt="2FA QR code" style={{ width: "100%", display: "block" }} /></div>}
              {enroll.secret && <div className="muted" style={{ fontSize: 11.5, textAlign: "center", marginBottom: 12, wordBreak: "break-all" }}>Or enter this key manually: <code>{enroll.secret}</code></div>}
              <input className="input" inputMode="numeric" autoComplete="one-time-code" placeholder="123456" value={code} onChange={(e) => setCode(e.target.value.replace(/\D/g, "").slice(0, 6))} style={{ marginBottom: 10, letterSpacing: 4, textAlign: "center", fontSize: 18 }} autoFocus />
              {err && <div style={{ color: "var(--danger)", fontSize: 12.5, marginBottom: 10 }}>{err}</div>}
              <div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
                <button className="btn" onClick={close}>Cancel</button>
                <button className="btn btn-primary" disabled={busy || code.length < 6} onClick={activate}>{busy ? "Verifying…" : "Verify & turn on"}</button>
              </div>
            </>}
            {open === "disable" && <>
              <h3 style={{ marginTop: 0 }}>Turn off two-factor</h3>
              <p className="muted" style={{ fontSize: 13 }}>Confirm your password to remove two-factor from your account.</p>
              <input className="input" type="password" placeholder="Current password" value={password} onChange={(e) => setPassword(e.target.value)} autoFocus style={{ marginBottom: 10 }} />
              {err && <div style={{ color: "var(--danger)", fontSize: 12.5, marginBottom: 10 }}>{err}</div>}
              <div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
                <button className="btn" onClick={close}>Cancel</button>
                <button className="btn" style={{ color: "var(--danger)" }} disabled={busy || !password} onClick={disable}>{busy ? "…" : "Turn off"}</button>
              </div>
            </>}
          </div>
        </div>
      )}
    </div>
  );
}

// Danger zone: permanent self-serve account deletion (GDPR/CCPA erasure).
function DeleteAccountManager() {
  const hub = window.useClearCast();
  const federated = Boolean(hub.data && hub.data.authProvider && hub.data.authProvider !== "password");
  const [open, setOpen] = React.useState(false);
  const [password, setPassword] = React.useState("");
  const [confirm, setConfirm] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");
  const run = async () => {
    setErr(""); setBusy(true);
    try { await hub.actions.deleteAccount(password, confirm); }
    catch (e) { setErr(e.message || "Could not delete account"); setBusy(false); }
  };
  return (
    <div>
      <button className="btn btn-sm" style={{ color: "var(--danger)", borderColor: "rgba(220,80,60,0.4)" }} onClick={() => setOpen(true)}>Delete account…</button>
      {open && (
        <div className="modal-overlay" onClick={() => !busy && setOpen(false)} style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.6)", display: "grid", placeItems: "center", zIndex: 1000 }}>
          <div className="card" onClick={(e) => e.stopPropagation()} style={{ width: 420, maxWidth: "92vw", padding: 22 }}>
            <h3 style={{ marginTop: 0, color: "var(--danger)" }}>Delete your account</h3>
            <p className="muted" style={{ fontSize: 13 }}>This permanently deletes your account, your businesses, posts, and uploaded media. Content already published on social platforms is not affected. <strong>This cannot be undone.</strong></p>
            {!federated && <input className="input" type="password" placeholder="Current password" value={password} onChange={(e) => setPassword(e.target.value)} style={{ marginBottom: 10 }} />}
            <input className="input" placeholder='Type DELETE to confirm' value={confirm} onChange={(e) => setConfirm(e.target.value)} style={{ marginBottom: 10 }} />
            {err && <div style={{ color: "var(--danger)", fontSize: 12.5, marginBottom: 10 }}>{err}</div>}
            <div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
              <button className="btn" onClick={() => setOpen(false)} disabled={busy}>Cancel</button>
              <button className="btn" style={{ background: "var(--danger)", color: "#fff" }} disabled={busy || (!federated && !password) || confirm.trim().toUpperCase() !== "DELETE"} onClick={run}>{busy ? "Deleting…" : "Permanently delete"}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// Enterprise SSO (SAML). Providers are registered per customer's IdP (admin only).
function SsoManager() {
  const hub = window.useClearCast();
  const isAdmin = Boolean(hub.data && hub.data.isAdmin);
  const [open, setOpen] = React.useState(false);
  const [loaded, setLoaded] = React.useState(false);
  const [providers, setProviders] = React.useState([]);
  const [sp, setSp] = React.useState(null);
  const [metadataUrl, setMetadataUrl] = React.useState("");
  const [domains, setDomains] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [msg, setMsg] = React.useState("");
  const load = async () => {
    try { const r = await ClearCastAPI.ssoListProviders(); setProviders(r.providers || []); setSp(r.sp || null); }
    catch (e) { setMsg(e.message || "Could not load SSO config"); }
    finally { setLoaded(true); }
  };
  const openPanel = () => { setOpen(true); if (!loaded) load(); };
  const register = async () => {
    setMsg(""); setBusy(true);
    try { await ClearCastAPI.ssoRegisterProvider({ metadataUrl, domains }); setMetadataUrl(""); setDomains(""); setMsg("Provider registered."); await load(); }
    catch (e) { setMsg(e.message || "Could not register provider"); }
    finally { setBusy(false); }
  };
  const remove = async (id) => {
    setBusy(true);
    try { await ClearCastAPI.ssoDeleteProvider(id); await load(); } catch (e) { setMsg(e.message || "Could not remove"); } finally { setBusy(false); }
  };

  if (!isAdmin) {
    return <div className="muted" style={{ fontSize: 12.5, maxWidth: 460 }}>SAML single sign-on is available on this plan. To connect your company's identity provider (Okta, Entra, Google Workspace, etc.), an admin can set it up in Settings → Security, or email <a href="mailto:support@clear-cast.net" style={{ color: "var(--accent-2)" }}>support@clear-cast.net</a>.</div>;
  }
  return (
    <div style={{ maxWidth: 560 }}>
      <button className="btn btn-sm" onClick={openPanel}>{open ? "Hide SSO setup" : "Set up SAML SSO"}</button>
      {open && (
        <div className="card" style={{ marginTop: 10, padding: 16 }}>
          <div style={{ fontSize: 12.5, color: "var(--text-2)", marginBottom: 10 }}>Give these to your IdP admin, then register the IdP's metadata URL below.</div>
          {sp ? (
            <div style={{ fontSize: 11.5, fontFamily: "monospace", background: "var(--bg-2)", borderRadius: 8, padding: 10, marginBottom: 12, wordBreak: "break-all" }}>
              <div><b>ACS URL:</b> {sp.acsUrl}</div>
              <div style={{ marginTop: 4 }}><b>Entity ID / Metadata:</b> {sp.entityId}</div>
            </div>
          ) : <div className="muted" style={{ fontSize: 12 }}>Loading SP details… (SSO must be enabled on the Supabase project first.)</div>}
          <div className="field-label">IdP metadata URL</div>
          <input className="input" placeholder="https://idp.company.com/app/metadata" value={metadataUrl} onChange={(e) => setMetadataUrl(e.target.value)} style={{ marginBottom: 8 }} />
          <div className="field-label">Email domains (comma-separated)</div>
          <input className="input" placeholder="company.com, company.co.uk" value={domains} onChange={(e) => setDomains(e.target.value)} style={{ marginBottom: 10 }} />
          <button className="btn btn-primary btn-sm" disabled={busy || !metadataUrl.trim()} onClick={register}>{busy ? "Saving…" : "Register provider"}</button>
          {msg && <div style={{ fontSize: 12, marginTop: 8, color: "var(--text-2)" }}>{msg}</div>}
          {providers.length > 0 && <div style={{ marginTop: 14 }}>
            <div className="field-label">Connected providers</div>
            {providers.map((p) => (
              <div key={p.id} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, padding: "8px 10px", border: "1px solid var(--border)", borderRadius: 8, marginTop: 6 }}>
                <div style={{ fontSize: 12.5 }}>{(p.domains || []).join(", ") || p.id}</div>
                <button className="btn btn-ghost btn-sm" onClick={() => remove(p.id)}>Remove</button>
              </div>
            ))}
          </div>}
        </div>
      )}
    </div>
  );
}

function SecuritySettings() {
  const hub = window.useClearCast();
  const auditLog = (hub.data && hub.data.auditLog) || [];
  const workspace = hub.data.workspace || {};
  const saved = workspace.securitySettings || {};
  // Only the real current session — no fabricated devices.
  const defaultSessions = [{ id: "current", d: "This device", loc: "", t: "Active now", cur: true }];
  const [twoFactorRequired, setTwoFactorRequired] = React.useState(saved.twoFactorRequired !== false);
  const [ssoEnabled, setSsoEnabled] = React.useState(Boolean(saved.ssoEnabled));
  const [sessionTimeout, setSessionTimeout] = React.useState(saved.sessionTimeout || "30 days");
  const [allowedDomains, setAllowedDomains] = React.useState(saved.allowedDomains || "");
  const [sessions, setSessions] = React.useState(saved.sessions || defaultSessions);
  const revokeSession = (id) => setSessions((current) => current.filter((session) => session.id !== id || session.cur));
  const reset = () => {
    setTwoFactorRequired(saved.twoFactorRequired !== false);
    setSsoEnabled(Boolean(saved.ssoEnabled));
    setSessionTimeout(saved.sessionTimeout || "30 days");
    setAllowedDomains(saved.allowedDomains || "");
    setSessions(saved.sessions || defaultSessions);
  };
  const save = () => hub.actions.saveWorkspace({
    ...workspace,
    securitySettings: { twoFactorRequired, ssoEnabled, sessionTimeout, allowedDomains, sessions }
  });
  return (
    <>
      <SettingsHeader title="Security" desc="Protect your account and workspace." />
      <Row label="Password" desc="Last changed 4 months ago.">
        <button className="btn" disabled title="Coming soon — password is managed by your identity provider for now">Change password</button>
      </Row>
      <Row label="Two-factor auth" desc="Protect your account with an authenticator-app code at sign-in.">
        <TwoFactorManager />
      </Row>
      <Row label="Single sign-on (SSO)" desc="SAML sign-in for your team via your identity provider.">
        <SsoManager />
      </Row>
      <Row label="Session timeout" desc="Inactive sessions are required to sign in again.">
        <select className="select" value={sessionTimeout} onChange={(event) => setSessionTimeout(event.target.value)} style={{ maxWidth: 220 }}>
          <option>7 days</option>
          <option>14 days</option>
          <option>30 days</option>
          <option>90 days</option>
        </select>
      </Row>
      <Row label="Allowed domains" desc="Recommended email domains for new teammate invites (comma-separated).">
        <input className="input" value={allowedDomains} onChange={(event) => setAllowedDomains(event.target.value)} placeholder="e.g. yourcompany.com" style={{ maxWidth: 420 }}/>
      </Row>
      <Row label="Active sessions" desc="Devices currently signed in.">
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {sessions.map(s => (
            <div key={s.id || s.d} style={{ display: "flex", alignItems: "center", padding: "10px 12px", border: "1px solid var(--border)", borderRadius: 10 }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13, fontWeight: 500 }}>{s.d} {s.cur && <span className="pill green" style={{ padding: "1px 7px", fontSize: 10, marginLeft: 6 }}>This device</span>}</div>
                <div style={{ fontSize: 11.5, color: "var(--text-3)", marginTop: 2 }}>{s.loc} · {s.t}</div>
              </div>
              {!s.cur && <button className="btn btn-ghost btn-sm" onClick={() => revokeSession(s.id)}>Revoke</button>}
            </div>
          ))}
        </div>
      </Row>
      <Row label="Account activity" desc="Recent sensitive actions recorded on this workspace.">
        <div style={{ display: "flex", flexDirection: "column", gap: 6, maxWidth: 480, maxHeight: 220, overflowY: "auto" }}>
          {auditLog.length ? auditLog.slice(0, 25).map((a) => (
            <div key={a.id} style={{ display: "flex", justifyContent: "space-between", gap: 12, padding: "8px 10px", border: "1px solid var(--border)", borderRadius: 8 }}>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontSize: 12.5, fontWeight: 500 }}>{a.action}{a.details ? <span className="muted" style={{ fontWeight: 400 }}> — {a.details}</span> : ""}</div>
                <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 2 }}>{a.actor}{a.role ? ` · ${a.role}` : ""}</div>
              </div>
              <div style={{ fontSize: 11, color: "var(--text-3)", whiteSpace: "nowrap" }}>{a.createdAt ? new Date(a.createdAt).toLocaleString() : ""}</div>
            </div>
          )) : <div className="muted" style={{ fontSize: 12.5 }}>No recorded activity yet.</div>}
        </div>
      </Row>
      <Row label="Delete account" desc="Permanently delete your account and all associated data.">
        <DeleteAccountManager />
      </Row>
      <SettingsSaveBar title="Security changes" onSave={save} onReset={reset} />
    </>
  );
}

function PublishingSettings() {
  const hub = window.useClearCast();
  const workspace = hub.data.workspace || {};
  const rules = workspace.publishingRules || {};
  const [quietStart, setQuietStart] = React.useState(rules.quietStart || "22:00");
  const [quietEnd, setQuietEnd] = React.useState(rules.quietEnd || "06:00");
  const [approvalRequired, setApprovalRequired] = React.useState(rules.approvalRequired !== false);
  const [hashtagLimit, setHashtagLimit] = React.useState(rules.hashtagLimit || 12);
  const [profanityFilter, setProfanityFilter] = React.useState(rules.profanityFilter !== false);
  const [duplicateDetection, setDuplicateDetection] = React.useState(Boolean(rules.duplicateDetection));
  const [autoPauseOutage, setAutoPauseOutage] = React.useState(rules.autoPauseOutage !== false);
  const retention = rules.mediaRetention || {};
  const [retentionOn, setRetentionOn] = React.useState(Boolean(retention.enabled));
  const [retentionDays, setRetentionDays] = React.useState(retention.days || 90);
  const reset = () => {
    setQuietStart(rules.quietStart || "22:00");
    setQuietEnd(rules.quietEnd || "06:00");
    setApprovalRequired(rules.approvalRequired !== false);
    setHashtagLimit(rules.hashtagLimit || 12);
    setProfanityFilter(rules.profanityFilter !== false);
    setDuplicateDetection(Boolean(rules.duplicateDetection));
    setAutoPauseOutage(rules.autoPauseOutage !== false);
    setRetentionOn(Boolean(retention.enabled));
    setRetentionDays(retention.days || 90);
  };
  const save = () => hub.actions.saveWorkspace({
    ...workspace,
    publishingRules: { quietStart, quietEnd, approvalRequired, hashtagLimit: Number(hashtagLimit) || 12, profanityFilter, duplicateDetection, autoPauseOutage,
      mediaRetention: { enabled: retentionOn, days: Math.max(1, Number(retentionDays) || 90) } }
  });
  return (
    <>
      <SettingsHeader title="Publishing rules" desc="Guardrails applied across all channels." />
      <Row label="Quiet hours" desc="Block automated publishing between these times.">
        <div style={{ display: "flex", gap: 8 }}>
          <input className="input" value={quietStart} onChange={(event) => setQuietStart(event.target.value)} style={{ maxWidth: 100 }}/>
          <span style={{ alignSelf: "center", color: "var(--text-3)" }}>to</span>
          <input className="input" value={quietEnd} onChange={(event) => setQuietEnd(event.target.value)} style={{ maxWidth: 100 }}/>
        </div>
      </Row>
      <Row label="Approval required" desc="Posts must be approved before publishing.">
        <Toggle on={approvalRequired} onChange={setApprovalRequired}/>
      </Row>
      <Row label="Hashtag limit" desc="Warn if a post exceeds N hashtags.">
        <input className="input" type="number" value={hashtagLimit} onChange={(event) => setHashtagLimit(event.target.value)} style={{ maxWidth: 100 }}/>
      </Row>
      <Row label="Profanity filter" desc="Block posts that contain restricted words.">
        <Toggle on={profanityFilter} onChange={setProfanityFilter}/>
      </Row>
      <Row label="Duplicate detection" desc="Flag if a draft is 90%+ similar to an existing post.">
        <Toggle on={duplicateDetection} onChange={setDuplicateDetection}/>
      </Row>
      <Row label="Auto-pause on outage" desc="Pause queue if a channel API is down for &gt;10 min.">
        <Toggle on={autoPauseOutage} onChange={setAutoPauseOutage}/>
      </Row>
      <Row label="Auto-delete published media" desc="Off by default. When on, media is removed from your library this many days AFTER it's published (the on-platform copy stays). Skips anything still scheduled, in approval, or in an evergreen queue.">
        <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
          <Toggle on={retentionOn} onChange={setRetentionOn}/>
          <input className="input" type="number" min="1" disabled={!retentionOn} value={retentionDays} onChange={(event) => setRetentionDays(event.target.value)} style={{ maxWidth: 90 }}/>
          <span style={{ color: "var(--text-3)", fontSize: 12 }}>days after publish</span>
        </div>
      </Row>
      <SettingsSaveBar title="Publishing rule changes" onSave={save} onReset={reset} />
    </>
  );
}

function AISettings() {
  const hub = window.useClearCast();
  const workspace = hub.data.workspace || {};
  const settings = workspace.aiSettings || {};
  const [model, setModel] = React.useState(settings.model || "Balanced (recommended)");
  const [voice, setVoice] = React.useState(settings.voice || workspace.brandVoice || "");
  const [autoDraft, setAutoDraft] = React.useState(Boolean(settings.autoDraft));
  const [refAccounts, setRefAccounts] = React.useState(Array.isArray(settings.referenceAccounts) ? settings.referenceAccounts : []);
  const [newRef, setNewRef] = React.useState("");
  const addRef = () => {
    const handle = newRef.trim().replace(/^@+/, "@").replace(/^([^@])/, "@$1");
    if (handle.length < 2 || refAccounts.includes(handle) || refAccounts.length >= 3) return;
    setRefAccounts((cur) => [...cur, handle]);
    setNewRef("");
  };
  const save = () => hub.actions.saveWorkspace({ ...workspace, aiSettings: { model, voice, autoDraft, referenceAccounts: refAccounts } });
  return (
    <>
      <SettingsHeader title="AI assistant" desc="Configure how the AI assistant drafts and recommends." />
      <Row label="Default model">
        <select className="select" value={model} onChange={(event) => setModel(event.target.value)} style={{ maxWidth: 360 }}>
          <option>Balanced (recommended)</option>
          <option>Faster, lighter drafts</option>
          <option>Higher quality, slower</option>
        </select>
      </Row>
      <Row label="Brand voice" desc="Paste examples of past posts the AI should mimic.">
        <textarea className="textarea" rows="4" style={{ maxWidth: 480 }} value={voice} onChange={(event) => setVoice(event.target.value)} placeholder="Describe your brand voice so AI drafts sound like you."/>
      </Row>
      <Row label="Reference accounts" desc="Up to 3 accounts the AI can study for tone.">
        <div style={{ display: "flex", flexDirection: "column", gap: 8, maxWidth: 360 }}>
          {refAccounts.map(h => (
            <div key={h} style={{ display: "flex", alignItems: "center", padding: "8px 12px", border: "1px solid var(--border)", borderRadius: 10 }}>
              <Icon.AtSign width="14" height="14" style={{ marginRight: 8, color: "var(--text-3)" }}/>
              <span style={{ flex: 1, fontSize: 13 }}>{h}</span>
              <button className="btn btn-ghost btn-sm" style={{ padding: 4 }} onClick={() => setRefAccounts((cur) => cur.filter((x) => x !== h))} aria-label={`Remove ${h}`}><Icon.X width="14" height="14" /></button>
            </div>
          ))}
          {refAccounts.length === 0 && <div style={{ fontSize: 12.5, color: "var(--text-3)" }}>No reference accounts yet.</div>}
          {refAccounts.length < 3 && (
            <div style={{ display: "flex", gap: 8 }}>
              <input className="input" placeholder="@handle" value={newRef} onChange={(e) => setNewRef(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); addRef(); } }} style={{ flex: 1 }} />
              <button className="btn btn-sm" onClick={addRef} disabled={!newRef.trim()}>Add</button>
            </div>
          )}
          <div style={{ fontSize: 11.5, color: "var(--text-3)" }}>Saved with your AI assistant changes below.</div>
        </div>
      </Row>
      <Row label="Auto-draft for empty slots" desc="When a queue slot is empty 24h before publish time, the AI drafts a candidate.">
        <Toggle on={autoDraft} onChange={setAutoDraft}/>
      </Row>
      <SettingsSaveBar title="AI assistant changes" onSave={save} />
    </>
  );
}

function ExportsSettings() {
  const hub = window.useClearCast();
  const workspace = hub.data.workspace || {};
  const settings = workspace.exportSettings || {};
  const [backupSchedule, setBackupSchedule] = React.useState(settings.backupSchedule || "Manual export only");
  const [confirmReset, setConfirmReset] = React.useState(false);
  const save = () => hub.actions.saveWorkspace({ ...workspace, exportSettings: { backupSchedule } });
  const exportJson = () => {
    try {
      const blob = new Blob([JSON.stringify(hub.data || {}, null, 2)], { type: "application/json" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `clearcast-${(workspace.name || "workspace").toLowerCase().replace(/[^a-z0-9]+/g, "-")}.json`;
      document.body.appendChild(a);
      a.click();
      a.remove();
      window.setTimeout(() => URL.revokeObjectURL(url), 1500);
      hub.toast("Workspace exported as JSON");
    } catch (error) { hub.toast("Could not export JSON"); }
  };
  const resetDemo = async () => {
    if (!confirmReset) {
      setConfirmReset(true);
      hub.toast("Confirm reset to restore the clean demo workspace");
      return;
    }
    await hub.actions.resetDemoData();
    setConfirmReset(false);
  };
  return (
    <>
      <SettingsHeader title="Exports & data" desc="Download or transfer your data." />
      <Row label="Export workspace" desc="Includes posts, drafts, comments, and analytics history.">
        <div style={{ display: "flex", gap: 10 }}>
          <button className="btn" onClick={() => hub.actions.exportReports()}><Icon.Download width="14" height="14" /> CSV</button>
          <button className="btn" onClick={exportJson}><Icon.Download width="14" height="14" /> JSON</button>
        </div>
      </Row>
      <Row label="Backup" desc="Export your workspace data anytime with the CSV/JSON buttons above.">
        <select className="select" value={backupSchedule} onChange={(event) => setBackupSchedule(event.target.value)} style={{ maxWidth: 360 }}>
          <option>Manual export only</option>
        </select>
      </Row>
      <SettingsSaveBar title="Export setting changes" onSave={save} />
      <Row label="Demo data reset" desc="Restore the clean ClearCast seed workspace for testing. This replaces local posts, inbox items, reports, integrations, team data, and settings. Uploaded files stay on disk, but the media library returns to seeded demo assets.">
        <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
          <button className="btn" onClick={resetDemo} style={{ color: "var(--danger)", borderColor: "rgba(239,68,68,0.3)" }}>
            <Icon.Trash width="14" height="14" /> {confirmReset ? "Confirm reset" : "Reset demo data"}
          </button>
          {confirmReset && <button className="btn btn-ghost" onClick={() => setConfirmReset(false)}>Cancel</button>}
        </div>
      </Row>
      <Row label="Delete workspace" desc="Production-only destructive action. Disabled in the local prototype.">
        <button className="btn" disabled style={{ color: "var(--text-3)", borderColor: "var(--border)", opacity: 0.55 }}><Icon.Trash width="14" height="14" /> Delete workspace</button>
      </Row>
    </>
  );
}

window.IntegrationsPage = IntegrationsPage;
window.SettingsPage = SettingsPage;
