// screens-b.jsx — Billing, White-label, Integrations, API & webhooks, Settings (live data)

const TXN_TYPE_LABEL = {
  topup: "Top-up",
  call_charge: "Call charge",
  sms_charge: "SMS",
  number_rental: "Number rental",
  cnam_lookup: "CNAM lookup",
  refund: "Refund",
  adjustment: "Adjustment",
};

function Billing({ workspace, reloadWorkspaces }) {
  const wid = workspace.id;
  const balance = useApi(() => API.billing.balance(wid), [wid]);
  const summary = useApi(() => API.billing.summary(wid), [wid]);
  const txns = useApi(() => API.billing.transactions(wid, { limit: 25 }), [wid]);
  const autoReload = useApi(() => API.billing.autoReload(wid), [wid]);

  const [amount, setAmount] = React.useState(100);
  const [topupBusy, setTopupBusy] = React.useState(false);
  const [topupErr, setTopupErr] = React.useState(null);
  const [showAuto, setShowAuto] = React.useState(false);

  async function topUp() {
    if (!amount || amount < 5) { setTopupErr("Minimum $5"); return; }
    setTopupBusy(true); setTopupErr(null);
    try {
      // In dev (no Stripe wired up), the API still requires a paymentMethodId. We fall back to
      // calling the onboarding fund endpoint which doesn't require one.
      await API.onboarding.fund({ workspaceId: wid, amountCents: amount * 100, paymentMethodId: "dev-skip" });
      balance.reload(); summary.reload(); txns.reload();
      reloadWorkspaces && reloadWorkspaces();
    } catch (err) { setTopupErr(err.message); }
    finally { setTopupBusy(false); }
  }

  const bal = balance.data || {};
  const summaryRows = (summary.data || []).slice().sort((a, b) => Number(b.totalCents || 0) - Number(a.totalCents || 0));
  const monthTotal = summaryRows.reduce((acc, r) => acc + Number(r.totalCents || 0), 0);

  return (
    <div className="page-inner wide">
      <div className="row between" style={{alignItems:"flex-start", marginBottom:24}}>
        <div>
          <div className="eyebrow">Account</div>
          <h1 className="page-title" style={{marginTop:6}}>Billing</h1>
          <div className="page-sub">Prepay wallet · no contracts · auto-reload when balance runs low</div>
        </div>
      </div>

      {balance.error && <ErrorChip msg={balance.error.message}/>}

      <div style={{display:"grid", gridTemplateColumns:"1.3fr 1fr", gap:16, marginBottom:16}}>
        <div className="card" style={{overflow:"hidden"}}>
          <div style={{padding:"24px 28px", background:"linear-gradient(135deg, color-mix(in oklab, var(--accent) 8%, var(--panel)) 0%, var(--panel) 100%)"}}>
            <div style={{fontSize:12, color:"var(--ink-4)", letterSpacing:".05em"}}>CURRENT BALANCE</div>
            <div className="serif" style={{fontSize:54, letterSpacing:"-0.02em", color:"var(--ink)", lineHeight:1, marginTop:8, fontVariantNumeric:"tabular-nums"}}>
              {bal.balanceFormatted || "$0.00"}
            </div>
            <div style={{fontSize:13, color:"var(--ink-3)", marginTop:8}}>
              {bal.burnRateDailyCents > 0
                ? `Burn ≈ ${fmtMoney(bal.burnRateDailyCents)}/day · ${bal.daysRemaining ?? "—"} days left`
                : "No spend yet — set up your first number to start tracking calls."}
            </div>
          </div>
          <div style={{padding:"20px 28px", borderTop:".5px solid var(--line)"}}>
            <div style={{fontSize:12, fontWeight:500, color:"var(--ink-3)", marginBottom:10}}>Quick top-up</div>
            <div className="row g8" style={{marginBottom:14, flexWrap:"wrap"}}>
              {[50, 100, 250, 500, 1000].map((a) => (
                <button key={a} className={"btn " + (amount === a ? "btn-primary" : "btn-secondary")} onClick={() => setAmount(a)}>
                  ${a}
                </button>
              ))}
              <input className="input" style={{width:100}} type="number" min="5" placeholder="Custom"
                onChange={(e) => { const n = parseInt(e.target.value, 10); if (!isNaN(n)) setAmount(n); }}/>
            </div>
            {topupErr && <ErrorChip msg={topupErr}/>}
            <div className="row g8">
              <button className="btn btn-primary btn-lg" style={{flex:1}} onClick={topUp} disabled={topupBusy}>
                {topupBusy ? "Processing…" : `Top up $${amount}`}
              </button>
              <button className="btn btn-secondary btn-lg" onClick={() => setShowAuto(true)}>
                {autoReload.data?.enabled ? "Edit auto-reload" : "Set up auto-reload"}
              </button>
            </div>
            <div style={{fontSize:12, color:"var(--ink-4)", marginTop:12}}>
              {autoReload.data?.enabled
                ? `Auto-reload: when balance < ${fmtMoney(autoReload.data.thresholdCents)}, top up ${fmtMoney(autoReload.data.reloadAmountCents)}`
                : "Dev mode: top-ups credit instantly without a real card."}
            </div>
          </div>
        </div>

        <div className="card">
          <div className="card-h"><h3>This month</h3><div className="sub">{new Date().toLocaleDateString(undefined, { month: "long", year: "numeric" })}</div></div>
          <div className="card-b col g14">
            {summary.loading && summaryRows.length === 0 && <div style={{color:"var(--ink-4)", fontSize:13}}>Loading…</div>}
            {!summary.loading && summaryRows.length === 0 && <div style={{color:"var(--ink-4)", fontSize:13}}>No charges yet this month.</div>}
            {summaryRows.map((r) => (
              <BillRow key={r.type} lbl={TXN_TYPE_LABEL[r.type] || r.type} v={fmtMoney(r.totalCents)} />
            ))}
            {summaryRows.length > 0 && (
              <>
                <div style={{height:".5px", background:"var(--line)"}}/>
                <div className="row between" style={{fontSize:15, fontWeight:500}}>
                  <span>Month-to-date</span><span className="num">{fmtMoney(monthTotal)}</span>
                </div>
              </>
            )}
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-h">
          <div><h3>Recent activity</h3><div className="sub">Wallet transactions</div></div>
          <button className="btn btn-ghost btn-sm" onClick={() => txns.reload()}><I.dl size={12}/> Refresh</button>
        </div>
        <table className="table">
          <thead><tr><th>Date</th><th>Type</th><th>Description</th><th style={{textAlign:"right"}}>Amount</th><th style={{textAlign:"right"}}>Balance after</th></tr></thead>
          <tbody>
            {txns.loading && <tr><td colSpan={5} style={{textAlign:"center", padding:30, color:"var(--ink-4)"}}>Loading…</td></tr>}
            {!txns.loading && (txns.data || []).length === 0 && <tr><td colSpan={5} style={{textAlign:"center", padding:30, color:"var(--ink-4)"}}>No transactions yet.</td></tr>}
            {(txns.data || []).map((t) => (
              <tr key={t.id}>
                <td style={{color:"var(--ink)", fontWeight:500}}>{new Date(t.createdAt).toLocaleString()}</td>
                <td><span className="pill">{TXN_TYPE_LABEL[t.type] || t.type}</span></td>
                <td className="muted">{t.description || "—"}</td>
                <td className="num" style={{textAlign:"right", color: Number(t.amountCents) >= 0 ? "var(--good)" : "var(--ink)"}}>
                  {Number(t.amountCents) >= 0 ? "+" : "−"}{fmtMoney(Math.abs(Number(t.amountCents)))}
                </td>
                <td className="num" style={{textAlign:"right"}}>{fmtMoney(t.balanceAfterCents)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {showAuto && <AutoReloadModal workspace={workspace} initial={autoReload.data} onClose={() => setShowAuto(false)} onSaved={() => { setShowAuto(false); autoReload.reload(); }}/>}
    </div>
  );
}

function AutoReloadModal({ workspace, initial, onClose, onSaved }) {
  const [enabled, setEnabled] = React.useState(initial?.enabled ?? false);
  const [threshold, setThreshold] = React.useState((initial?.thresholdCents ?? 2000) / 100);
  const [reload, setReload] = React.useState((initial?.reloadAmountCents ?? 10000) / 100);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  async function submit(e) {
    e.preventDefault();
    setBusy(true); setErr(null);
    try {
      await API.billing.updateAutoReload(workspace.id, {
        enabled,
        thresholdCents: Math.round(threshold * 100),
        reloadAmountCents: Math.round(reload * 100),
      });
      onSaved && onSaved();
    } catch (err) { setErr(err.message); }
    finally { setBusy(false); }
  }

  return (
    <Modal onClose={onClose} title="Auto-reload">
      <form onSubmit={submit} className="col g16">
        <Toggle label="Enable auto-reload" sub="Charge default card when balance drops below threshold" value={enabled} onChange={setEnabled}/>
        <div className="field"><label>Threshold (USD)</label>
          <input className="input" type="number" min="1" step="1" value={threshold} onChange={(e) => setThreshold(Number(e.target.value))}/>
        </div>
        <div className="field"><label>Reload amount (USD)</label>
          <input className="input" type="number" min="5" step="5" value={reload} onChange={(e) => setReload(Number(e.target.value))}/>
        </div>
        {err && <ErrorChip msg={err}/>}
        <div className="row g8" style={{justifyContent:"flex-end"}}>
          <button type="button" className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
          <button type="submit" className="btn btn-primary btn-sm" disabled={busy}>{busy ? "Saving…" : "Save"}</button>
        </div>
      </form>
    </Modal>
  );
}

function BillRow({ lbl, detail, v, muted }) {
  return (
    <div className="row between">
      <div>
        <div style={{fontSize:13.5, color:"var(--ink-2)", fontWeight:500}}>{lbl}</div>
        {detail && <div className="muted" style={{fontSize:12}}>{detail}</div>}
      </div>
      <div className="num" style={{fontWeight:500, color: muted ? "var(--ink-4)" : "var(--ink)"}}>{v}</div>
    </div>
  );
}

// ── White-label ────────────────────────────────────────────────────

function WhiteLabel({ workspace, brand, setBrand }) {
  const wid = workspace.id;
  const wl = useApi(() => API.whitelabel.get(wid), [wid]);
  const [form, setForm] = React.useState(null);
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [okMsg, setOkMsg] = React.useState(null);
  const fileRef = React.useRef();

  React.useEffect(() => {
    if (!wl.data) return;
    setForm({
      brandName: wl.data.brandName || workspace.name,
      accentColor: wl.data.accentColor || "#6366F1",
      logoUrl: wl.data.logoUrl || "",
      customDomain: wl.data.customDomain || "",
      fromEmail: wl.data.fromEmail || "",
      hidePlatformBrand: wl.data.hidePlatformBrand ?? false,
      clientPdfBranding: wl.data.clientPdfBranding ?? true,
    });
  }, [wl.data, workspace.name]);

  if (wl.loading || !form) {
    return <div className="page-inner wide"><div style={{padding:30, color:"var(--ink-4)"}}>Loading…</div></div>;
  }

  const setF = (k, v) => setForm((f) => ({ ...f, [k]: v }));

  async function save() {
    setSaving(true); setError(null); setOkMsg(null);
    try {
      await API.whitelabel.patch(wid, {
        brandName: form.brandName,
        accentColor: form.accentColor,
        customDomain: form.customDomain || null,
        fromEmail: form.fromEmail || null,
        hidePlatformBrand: form.hidePlatformBrand,
        clientPdfBranding: form.clientPdfBranding,
      });
      setBrand && setBrand({ name: form.brandName, accent: form.accentColor, logoUrl: wl.data?.logoUrl || null });
      // Apply accent globally so chrome (sidebar / buttons / charts) reflects
      // the new brand color without a full refresh.
      try { document.documentElement.style.setProperty("--accent", form.accentColor); } catch {}
      wl.reload();
      setOkMsg("Saved.");
      setTimeout(() => setOkMsg(null), 1800);
    } catch (err) { setError(err.message); }
    finally { setSaving(false); }
  }

  async function uploadLogo(file) {
    setSaving(true); setError(null);
    try {
      await API.whitelabel.uploadLogo(wid, file);
      wl.reload();
    } catch (err) { setError(err.message); }
    finally { setSaving(false); }
  }

  async function removeLogo() {
    const ok = await window.confirmDialog({
      title: "Remove logo",
      message: "Clients will see your brand initial again until you upload a new logo.",
      confirmLabel: "Remove",
    });
    if (!ok) return;
    setSaving(true);
    try { await API.whitelabel.deleteLogo(wid); wl.reload(); window.toast.success("Logo removed"); }
    catch (err) { setError(err.message); }
    finally { setSaving(false); }
  }

  return (
    <div className="page-inner wide">
      <div className="row between" style={{alignItems:"flex-start", marginBottom:24}}>
        <div>
          <div className="eyebrow">Account</div>
          <h1 className="page-title" style={{marginTop:6}}>White-label</h1>
          <div className="page-sub">Replace our brand with yours · clients never see us</div>
        </div>
        <div className="row g8">
          {okMsg && <span style={{color:"var(--good)", fontSize:13, alignSelf:"center"}}>{okMsg}</span>}
          <button className="btn btn-primary" onClick={save} disabled={saving}>{saving ? "Saving…" : "Save changes"}</button>
        </div>
      </div>

      {error && <ErrorChip msg={error}/>}

      <div style={{display:"grid", gridTemplateColumns:"1fr 1.2fr", gap:16}}>
        <div className="col g16">
          <div className="card">
            <div className="card-h"><h3>Brand identity</h3></div>
            <div className="card-b col g16">
              <div className="field"><label>Brand name</label>
                <input className="input" value={form.brandName} onChange={(e) => setF("brandName", e.target.value)}/>
              </div>
              <div className="field"><label>Logo</label>
                {form.logoUrl ? (
                  <div className="row g12" style={{padding:14, border:".5px solid var(--line)", borderRadius:"var(--radius)"}}>
                    <img src={form.logoUrl} alt="logo" style={{height:40, maxWidth:120, objectFit:"contain"}}/>
                    <div style={{flex:1}}/>
                    <button className="btn btn-ghost btn-sm" onClick={() => fileRef.current?.click()}>Replace</button>
                    <button className="btn btn-ghost btn-sm" style={{color:"var(--bad)"}} onClick={removeLogo}>Remove</button>
                  </div>
                ) : (
                  <div onClick={() => fileRef.current?.click()}
                    style={{padding:"18px", border:"1.5px dashed var(--line-2)", borderRadius:"var(--radius)", textAlign:"center", color:"var(--ink-4)", fontSize:12.5, cursor:"pointer"}}>
                    <I.upload size={18} style={{marginBottom:6}}/>
                    <div>Click to upload PNG, JPG or SVG · 512×512 recommended</div>
                  </div>
                )}
                <input ref={fileRef} type="file" accept="image/*" style={{display:"none"}}
                  onChange={(e) => e.target.files?.[0] && uploadLogo(e.target.files[0])}/>
              </div>
              <div className="field"><label>Accent color</label>
                <div className="row g8" style={{flexWrap:"wrap"}}>
                  {["#0A84FF","#6366F1","#9333EA","#DB2777","#DC2626","#F97316","#16A34A","#0D9488","#0F172A"].map((c) => (
                    <button key={c} onClick={() => setF("accentColor", c)} style={{width:28, height:28, borderRadius:8, background:c, border: form.accentColor === c ? "2px solid var(--ink)" : ".5px solid var(--line-2)"}}/>
                  ))}
                  <input className="input" style={{width:110}} value={form.accentColor} onChange={(e) => setF("accentColor", e.target.value)}/>
                </div>
              </div>
            </div>
          </div>
          <div className="card">
            <div className="card-h"><h3>Domain & email</h3></div>
            <div className="card-b col g16">
              <div className="field"><label>Custom subdomain</label>
                <input className="input" value={form.customDomain} onChange={(e) => setF("customDomain", e.target.value)} placeholder="app.yourdomain.com"/>
                <div className="muted" style={{fontSize:12}}>CNAME to <span className="mono">cname.calltrack.io</span> · TLS auto-renewed</div>
              </div>
              <div className="field"><label>Outbound emails "from"</label>
                <input className="input" value={form.fromEmail} onChange={(e) => setF("fromEmail", e.target.value)} placeholder="notifications@yourdomain.com"/>
              </div>
              <Toggle label="Hide our brand completely" sub="No mentions in product, emails, or receipts" value={form.hidePlatformBrand} onChange={(v) => setF("hidePlatformBrand", v)}/>
              <Toggle label="Use your logo on PDF reports" sub="Client-facing exports use your colors" value={form.clientPdfBranding} onChange={(v) => setF("clientPdfBranding", v)}/>
            </div>
          </div>
        </div>

        <div className="card" style={{position:"sticky", top:16, alignSelf:"flex-start"}}>
          <div className="card-h"><h3>Live preview</h3><div className="sub">How clients see the dashboard</div></div>
          <div style={{padding:16, background:"var(--bg-sunken)"}}>
            <div style={{borderRadius:"var(--radius-lg)", background:"var(--panel)", boxShadow:"var(--shadow-md)", overflow:"hidden"}}>
              <div style={{padding:"14px 18px", borderBottom:".5px solid var(--line)", display:"flex", alignItems:"center", gap:10}}>
                {form.logoUrl
                  ? <img src={form.logoUrl} alt="logo" style={{height:24, maxWidth:60, objectFit:"contain"}}/>
                  : <div style={{width:28, height:28, borderRadius:7, background: form.accentColor, display:"grid", placeItems:"center", color:"white", fontSize:12, fontWeight:700}}>
                      {form.brandName.slice(0,1).toUpperCase()}
                    </div>}
                <div style={{fontSize:14, fontWeight:500}}>{form.brandName}</div>
              </div>
              <div style={{padding:"20px 18px"}}>
                <div className="serif" style={{fontSize:22, marginBottom:4}}>Welcome back</div>
                <div style={{fontSize:12, color:"var(--ink-4)"}}>{form.hidePlatformBrand ? "" : `Powered by ${form.brandName}`}</div>
                <div style={{display:"grid", gridTemplateColumns:"1fr 1fr", gap:10, marginTop:16}}>
                  <div style={{padding:12, borderRadius:8, background:"var(--bg-elev)", border:".5px solid var(--line)"}}>
                    <div style={{fontSize:10, color:"var(--ink-4)"}}>Calls today</div>
                    <div className="serif num" style={{fontSize:22, color: form.accentColor}}>412</div>
                  </div>
                  <div style={{padding:12, borderRadius:8, background:"var(--bg-elev)", border:".5px solid var(--line)"}}>
                    <div style={{fontSize:10, color:"var(--ink-4)"}}>Answered</div>
                    <div className="serif num" style={{fontSize:22}}>89%</div>
                  </div>
                </div>
                <button style={{marginTop:14, width:"100%", height:32, borderRadius:7, border:0, background: form.accentColor, color:"white", fontSize:13, fontWeight:500}}>View call log</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Integrations ──────────────────────────────────────────────────

const PROVIDER_META = {
  hubspot:           { name: "HubSpot",          cat: "CRM",        icon: "HS", color: "#FF5C35", desc: "Push calls as engagements, sync contacts" },
  salesforce:        { name: "Salesforce",       cat: "CRM",        icon: "SF", color: "#00A1E0", desc: "Create leads from qualified calls" },
  zapier:            { name: "Zapier",           cat: "Automation", icon: "Z",  color: "#FF4A00", desc: "3,000+ apps via webhooks & triggers" },
  slack:             { name: "Slack",            cat: "Messaging",  icon: "S",  color: "#4A154B", desc: "Post missed calls & summaries" },
  google_analytics:  { name: "Google Analytics", cat: "Analytics",  icon: "GA", color: "#F9AB00", desc: "Send calls as GA4 events" },
  meta_ads:          { name: "Meta Ads",         cat: "Ads",        icon: "M",  color: "#0866FF", desc: "Offline conversions API" },
  google_ads:        { name: "Google Ads",       cat: "Ads",        icon: "G",  color: "#4285F4", desc: "Call conversions & GCLID import" },
  mailchimp:         { name: "Mailchimp",        cat: "Email",      icon: "MC", color: "#FFE01B", desc: "Tag subscribers on call" },
};

function Integrations({ workspace }) {
  const wid = workspace.id;
  const list = useApi(() => API.integrations.list(wid), [wid]);
  const [editing, setEditing] = React.useState(null);

  const items = list.data || [];

  return (
    <div className="page-inner wide">
      <div className="row between" style={{alignItems:"flex-start", marginBottom:24}}>
        <div>
          <div className="eyebrow">Account</div>
          <h1 className="page-title" style={{marginTop:6}}>Integrations</h1>
          <div className="page-sub">Connect your CRM, ad platforms, and analytics</div>
        </div>
      </div>

      {list.error && <ErrorChip msg={list.error.message}/>}

      <div style={{display:"grid", gridTemplateColumns:"repeat(3, 1fr)", gap:12}}>
        {items.map((it) => {
          const meta = PROVIDER_META[it.provider] || { name: it.provider, cat: "—", icon: "?", color: "#999", desc: "" };
          return (
            <div key={it.provider} className="card" style={{padding:18}}>
              <div className="row g12" style={{marginBottom:12}}>
                <div style={{width:36, height:36, borderRadius:8, background: meta.color, color:"white", fontSize:12, fontWeight:700, display:"grid", placeItems:"center"}}>{meta.icon}</div>
                <div style={{flex:1}}>
                  <div style={{fontSize:14, fontWeight:500}}>{meta.name}</div>
                  <div className="muted" style={{fontSize:11.5}}>{meta.cat}</div>
                </div>
                {it.connected && it.enabled && <span className="pill good"><span className="dot"/>Active</span>}
                {it.connected && !it.enabled && <span className="pill warn"><span className="dot"/>Paused</span>}
              </div>
              <div style={{fontSize:12.5, color:"var(--ink-3)", lineHeight:1.5, minHeight:34}}>{meta.desc}</div>
              <div style={{marginTop:12, paddingTop:12, borderTop:".5px solid var(--line)"}}>
                <button className={it.connected ? "btn btn-secondary btn-sm" : "btn btn-primary btn-sm"} style={{width:"100%"}}
                  onClick={() => setEditing(it)}>
                  {it.connected ? "Configure" : "Connect"}
                </button>
              </div>
            </div>
          );
        })}
      </div>

      {editing && <IntegrationModal workspace={workspace} integration={editing} onClose={() => setEditing(null)} onSaved={() => { setEditing(null); list.reload(); }}/>}
    </div>
  );
}

function IntegrationModal({ workspace, integration, onClose, onSaved }) {
  const wid = workspace.id;
  const meta = PROVIDER_META[integration.provider] || { name: integration.provider };
  const [config, setConfig] = React.useState(JSON.stringify(integration.config || {}, null, 2));
  const [enabled, setEnabled] = React.useState(integration.enabled ?? true);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  async function save(e) {
    e.preventDefault();
    setBusy(true); setErr(null);
    try {
      let parsed = {};
      try { parsed = JSON.parse(config || "{}"); }
      catch { setErr("Config must be valid JSON"); setBusy(false); return; }
      if (integration.connected) {
        await API.integrations.patch(wid, integration.provider, { config: parsed, enabled });
      } else {
        await API.integrations.connect(wid, integration.provider, parsed);
      }
      onSaved && onSaved();
    } catch (err) { setErr(err.message); }
    finally { setBusy(false); }
  }

  async function disconnect() {
    const ok = await window.confirmDialog({
      title: `Disconnect ${meta.name}`,
      message: "Stored credentials are deleted. Re-connect any time.",
      confirmLabel: "Disconnect",
      danger: true,
    });
    if (!ok) return;
    try { await API.integrations.disconnect(wid, integration.provider); window.toast.success(`${meta.name} disconnected`); onSaved && onSaved(); }
    catch (err) { window.toast.error(err.message); }
  }

  return (
    <Modal onClose={onClose} title={integration.connected ? `Configure ${meta.name}` : `Connect ${meta.name}`}>
      <form onSubmit={save} className="col g16">
        {integration.connected && (
          <Toggle label="Enabled" sub="Pause without deleting credentials" value={enabled} onChange={setEnabled}/>
        )}
        <div className="field"><label>Configuration (JSON)</label>
          <textarea className="input" rows={6} value={config} onChange={(e) => setConfig(e.target.value)}
            placeholder='{ "apiKey": "..." }'
            style={{fontFamily:"var(--mono, monospace)", fontSize:12}}/>
          <div className="muted" style={{fontSize:11.5}}>Secret fields (apiKey, token, secret, password) are hidden when fetched.</div>
        </div>
        {err && <ErrorChip msg={err}/>}
        <div className="row g8" style={{justifyContent:"space-between"}}>
          {integration.connected
            ? <button type="button" className="btn btn-ghost btn-sm" style={{color:"var(--bad)"}} onClick={disconnect}>Disconnect</button>
            : <span/>}
          <div className="row g8">
            <button type="button" className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
            <button type="submit" className="btn btn-primary btn-sm" disabled={busy}>{busy ? "Saving…" : "Save"}</button>
          </div>
        </div>
      </form>
    </Modal>
  );
}

// ── API keys & Webhooks ───────────────────────────────────────────

function APIKeys({ workspace }) {
  const wid = workspace.id;
  const keys = useApi(() => API.apiKeys.list(wid), [wid]);
  const hooks = useApi(() => API.webhooks.list(wid), [wid]);
  const [showKeyModal, setShowKeyModal] = React.useState(false);
  const [showHookModal, setShowHookModal] = React.useState(false);
  const [editingHook, setEditingHook] = React.useState(null);
  const [openDeliveriesFor, setOpenDeliveriesFor] = React.useState(null);

  return (
    <div className="page-inner wide">
      <div className="row between" style={{alignItems:"flex-start", marginBottom:24}}>
        <div>
          <div className="eyebrow">Account</div>
          <h1 className="page-title" style={{marginTop:6}}>API & webhooks</h1>
          <div className="page-sub">REST API and event webhooks</div>
        </div>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-h">
          <div><h3>API keys</h3><div className="sub">Use with <span className="mono">Bearer</span> authentication</div></div>
          <button className="btn btn-primary btn-sm" onClick={() => setShowKeyModal(true)}><I.plus size={13}/> New key</button>
        </div>
        <table className="table">
          <thead><tr><th>Name</th><th>Prefix</th><th>Scope</th><th>Env</th><th>Last used</th><th>Status</th><th style={{width:60}}></th></tr></thead>
          <tbody>
            {keys.loading && <tr><td colSpan={7} style={{textAlign:"center", padding:30, color:"var(--ink-4)"}}>Loading…</td></tr>}
            {!keys.loading && (keys.data || []).length === 0 && <tr><td colSpan={7} style={{textAlign:"center", padding:30, color:"var(--ink-4)"}}>No API keys yet</td></tr>}
            {(keys.data || []).map((k) => (
              <tr key={k.id}>
                <td style={{fontWeight:500}}>{k.name}</td>
                <td className="mono">{k.keyPrefix}…</td>
                <td><span className="pill info">{(k.scope || []).join(" · ")}</span></td>
                <td><span className="pill">{k.environment}</span></td>
                <td className="muted">{k.lastUsedAt ? fmtRelative(k.lastUsedAt) : "Never"}</td>
                <td>{k.revokedAt ? <span className="pill bad"><span className="dot"/>Revoked</span> : <span className="pill good"><span className="dot"/>Active</span>}</td>
                <td>
                  <div className="row g4">
                    {!k.revokedAt && (
                      <button className="btn btn-ghost btn-sm" onClick={async () => {
                        const ok = await window.confirmDialog({
                          title: "Revoke API key",
                          message: `Any service using "${k.name}" will start getting 401s immediately.`,
                          confirmLabel: "Revoke",
                          danger: true,
                        });
                        if (!ok) return;
                        try { await API.apiKeys.revoke(wid, k.id); keys.reload(); window.toast.success("Key revoked"); }
                        catch (err) { window.toast.error(err.message); }
                      }}>Revoke</button>
                    )}
                    <button className="icon-btn" title="Delete" onClick={async () => {
                      const ok = await window.confirmDialog({
                        title: "Delete API key",
                        message: `Permanently delete "${k.name}"? This cannot be undone.`,
                        confirmLabel: "Delete",
                        danger: true,
                      });
                      if (!ok) return;
                      try { await API.apiKeys.delete(wid, k.id); keys.reload(); window.toast.success("Key deleted"); }
                      catch (err) { window.toast.error(err.message); }
                    }}><I.x size={14}/></button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="card" style={{marginBottom:16}}>
        <div className="card-h">
          <div><h3>Webhooks</h3><div className="sub">POST to your endpoints on call events</div></div>
          <button className="btn btn-primary btn-sm" onClick={() => { setEditingHook(null); setShowHookModal(true); }}><I.plus size={13}/> Add endpoint</button>
        </div>
        <table className="table">
          <thead><tr><th>URL</th><th>Events</th><th>Status</th><th style={{textAlign:"right"}}>Deliveries</th><th style={{width:120}}></th></tr></thead>
          <tbody>
            {hooks.loading && <tr><td colSpan={5} style={{textAlign:"center", padding:30, color:"var(--ink-4)"}}>Loading…</td></tr>}
            {!hooks.loading && (hooks.data || []).length === 0 && <tr><td colSpan={5} style={{textAlign:"center", padding:30, color:"var(--ink-4)"}}>No webhooks yet</td></tr>}
            {(hooks.data || []).map((h) => (
              <tr key={h.id}>
                <td className="mono" style={{color:"var(--ink)", maxWidth:340, overflow:"hidden", textOverflow:"ellipsis"}}>{h.url}</td>
                <td>{(h.events || []).map((e) => <span key={e} className="pill" style={{marginRight:4}}>{e}</span>)}</td>
                <td>
                  {!h.enabled
                    ? <span className="pill warn"><span className="dot"/>Paused</span>
                    : h.failureCount > 0
                      ? <span className="pill bad"><span className="dot"/>{h.failureCount} failed</span>
                      : <span className="pill good"><span className="dot"/>Healthy</span>}
                </td>
                <td className="num" style={{textAlign:"right"}}>{h.deliveryCount || 0}</td>
                <td>
                  <div className="row g4">
                    <button className="btn btn-ghost btn-sm" onClick={() => setOpenDeliveriesFor(h)}>Logs</button>
                    <button className="btn btn-ghost btn-sm" onClick={() => { setEditingHook(h); setShowHookModal(true); }}>Edit</button>
                    <button className="icon-btn" title="Delete" onClick={async () => {
                      const ok = await window.confirmDialog({
                        title: "Delete webhook",
                        message: "Existing delivery logs are kept, but no new events will be sent.",
                        confirmLabel: "Delete",
                        danger: true,
                      });
                      if (!ok) return;
                      try { await API.webhooks.delete(wid, h.id); hooks.reload(); window.toast.success("Webhook deleted"); }
                      catch (err) { window.toast.error(err.message); }
                    }}><I.x size={14}/></button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {showKeyModal && <ApiKeyCreateModal workspace={workspace} onClose={() => setShowKeyModal(false)} onSaved={() => { setShowKeyModal(false); keys.reload(); }}/>}
      {showHookModal && <WebhookModal workspace={workspace} hook={editingHook} onClose={() => setShowHookModal(false)} onSaved={() => { setShowHookModal(false); hooks.reload(); }}/>}
      {openDeliveriesFor && <DeliveriesModal workspace={workspace} hook={openDeliveriesFor} onClose={() => setOpenDeliveriesFor(null)}/>}
    </div>
  );
}

function ApiKeyCreateModal({ workspace, onClose, onSaved }) {
  const [name, setName] = React.useState("");
  const [scope, setScope] = React.useState(["read"]);
  const [env, setEnv] = React.useState("live");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [createdKey, setCreatedKey] = React.useState(null);

  function toggleScope(s) {
    setScope((cur) => cur.includes(s) ? cur.filter((x) => x !== s) : [...cur, s]);
  }

  async function submit(e) {
    e.preventDefault();
    if (!name.trim() || scope.length === 0) { setErr("Name and at least one scope required"); return; }
    setBusy(true); setErr(null);
    try {
      const res = await API.apiKeys.create(workspace.id, { name: name.trim(), scope, environment: env });
      setCreatedKey(res.data.fullKey);
    } catch (err) { setErr(err.message); }
    finally { setBusy(false); }
  }

  if (createdKey) {
    return (
      <Modal onClose={() => { onSaved && onSaved(); }} title="API key created">
        <div className="col g16">
          <div style={{fontSize:13, color:"var(--ink-3)"}}>This is the only time the full key will be shown. Copy it now.</div>
          <div className="mono" style={{padding:14, background:"var(--bg-sunken)", borderRadius:8, fontSize:12, wordBreak:"break-all", color:"var(--ink)"}}>
            {createdKey}
          </div>
          <div className="row g8" style={{justifyContent:"flex-end"}}>
            <button className="btn btn-secondary btn-sm" onClick={() => navigator.clipboard?.writeText(createdKey)}>Copy</button>
            <button className="btn btn-primary btn-sm" onClick={() => { onSaved && onSaved(); }}>Done</button>
          </div>
        </div>
      </Modal>
    );
  }

  return (
    <Modal onClose={onClose} title="New API key">
      <form onSubmit={submit} className="col g16">
        <div className="field"><label>Name</label>
          <input className="input" value={name} onChange={(e) => setName(e.target.value)} required autoFocus placeholder="Production server"/>
        </div>
        <div className="field"><label>Scope</label>
          <div className="row g8">
            <label className="row g8" style={{cursor:"pointer"}}>
              <input type="checkbox" checked={scope.includes("read")} onChange={() => toggleScope("read")}/> Read
            </label>
            <label className="row g8" style={{cursor:"pointer"}}>
              <input type="checkbox" checked={scope.includes("write")} onChange={() => toggleScope("write")}/> Write
            </label>
          </div>
        </div>
        <div className="field"><label>Environment</label>
          <select className="select" value={env} onChange={(e) => setEnv(e.target.value)}>
            <option value="live">Live</option>
            <option value="test">Test</option>
          </select>
        </div>
        {err && <ErrorChip msg={err}/>}
        <div className="row g8" style={{justifyContent:"flex-end"}}>
          <button type="button" className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
          <button type="submit" className="btn btn-primary btn-sm" disabled={busy}>{busy ? "Creating…" : "Create"}</button>
        </div>
      </form>
    </Modal>
  );
}

const WEBHOOK_EVENTS = ["call.completed", "call.qualified", "call.missed", "voicemail.received", "call.recorded"];

function WebhookModal({ workspace, hook, onClose, onSaved }) {
  const isEdit = !!hook;
  const [url, setUrl] = React.useState(hook?.url || "");
  const [events, setEvents] = React.useState(hook?.events || ["call.completed"]);
  const [enabled, setEnabled] = React.useState(hook?.enabled ?? true);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [createdSecret, setCreatedSecret] = React.useState(null);

  function toggleEvent(e) {
    setEvents((cur) => cur.includes(e) ? cur.filter((x) => x !== e) : [...cur, e]);
  }

  async function submit(e) {
    e.preventDefault();
    if (!url.trim() || events.length === 0) { setErr("URL and at least one event required"); return; }
    setBusy(true); setErr(null);
    try {
      if (isEdit) {
        await API.webhooks.patch(workspace.id, hook.id, { url, events, enabled });
        onSaved && onSaved();
      } else {
        const res = await API.webhooks.create(workspace.id, { url, events });
        setCreatedSecret(res.data.signingSecret);
      }
    } catch (err) { setErr(err.message); }
    finally { setBusy(false); }
  }

  if (createdSecret) {
    return (
      <Modal onClose={() => { onSaved && onSaved(); }} title="Webhook created">
        <div className="col g16">
          <div style={{fontSize:13, color:"var(--ink-3)"}}>Use this signing secret to verify incoming webhook requests via the <span className="mono">X-CT-Signature</span> header (HMAC-SHA256 over the request body).</div>
          <div className="mono" style={{padding:14, background:"var(--bg-sunken)", borderRadius:8, fontSize:12, wordBreak:"break-all", color:"var(--ink)"}}>
            {createdSecret}
          </div>
          <div className="row g8" style={{justifyContent:"flex-end"}}>
            <button className="btn btn-secondary btn-sm" onClick={() => navigator.clipboard?.writeText(createdSecret)}>Copy</button>
            <button className="btn btn-primary btn-sm" onClick={() => onSaved && onSaved()}>Done</button>
          </div>
        </div>
      </Modal>
    );
  }

  return (
    <Modal onClose={onClose} title={isEdit ? "Edit webhook" : "Add webhook"}>
      <form onSubmit={submit} className="col g16">
        <div className="field"><label>URL</label>
          <input className="input" type="url" value={url} onChange={(e) => setUrl(e.target.value)} required autoFocus placeholder="https://example.com/hook"/>
        </div>
        <div className="field"><label>Events</label>
          <div className="col g8">
            {WEBHOOK_EVENTS.map((e) => (
              <label key={e} className="row g8" style={{cursor:"pointer", fontSize:13}}>
                <input type="checkbox" checked={events.includes(e)} onChange={() => toggleEvent(e)}/> {e}
              </label>
            ))}
          </div>
        </div>
        {isEdit && <Toggle label="Enabled" sub="Pause without deleting" value={enabled} onChange={setEnabled}/>}
        {err && <ErrorChip msg={err}/>}
        <div className="row g8" style={{justifyContent:"flex-end"}}>
          <button type="button" className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
          <button type="submit" className="btn btn-primary btn-sm" disabled={busy}>{busy ? "Saving…" : (isEdit ? "Save" : "Create")}</button>
        </div>
      </form>
    </Modal>
  );
}

function DeliveriesModal({ workspace, hook, onClose }) {
  const wid = workspace.id;
  const dels = useApi(() => API.webhooks.deliveries(wid, hook.id, { limit: 25 }), [wid, hook.id]);
  const rows = dels.data || [];
  return (
    <Modal onClose={onClose} title={`Deliveries · ${hook.url.slice(0, 40)}…`}>
      <div className="col g8" style={{maxHeight:480, overflow:"auto"}}>
        {dels.loading && <div style={{padding:20, color:"var(--ink-4)", textAlign:"center"}}>Loading…</div>}
        {!dels.loading && rows.length === 0 && <div style={{padding:20, color:"var(--ink-4)", textAlign:"center"}}>No deliveries yet.</div>}
        {rows.map((d) => (
          <div key={d.id} className="row g8" style={{padding:"8px 12px", background:"var(--bg-sunken)", borderRadius:6, fontSize:12}}>
            <span className={"pill " + (d.success ? "good" : "bad")} style={{height:18, fontSize:10, minWidth:60, textAlign:"center"}}>
              {d.httpStatus || (d.success ? "OK" : "ERR")}
            </span>
            <span className="mono" style={{flex:1, color:"var(--ink-2)"}}>{d.eventType}</span>
            <span style={{color:"var(--ink-4)"}}>{d.durationMs}ms</span>
            <span style={{color:"var(--ink-4)"}}>{fmtRelative(d.deliveredAt)}</span>
          </div>
        ))}
      </div>
    </Modal>
  );
}

// ── Settings ──────────────────────────────────────────────────────

function Settings({ workspace, reloadWorkspaces }) {
  const wid = workspace.id;
  const sett = useApi(() => API.settings.get(wid), [wid]);
  const [form, setForm] = React.useState(null);
  const [name, setName] = React.useState(workspace.name);
  const [saving, setSaving] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [okMsg, setOkMsg] = React.useState(null);

  React.useEffect(() => {
    if (!sett.data) return;
    setForm({
      timezone: sett.data.timezone || workspace.timezone || "America/New_York",
      country: sett.data.country || workspace.country || "US",
      recordingConsentWhisper: sett.data.recordingConsentWhisper ?? true,
      piiRedaction: sett.data.piiRedaction ?? true,
      twoFactorRequired: sett.data.twoFactorRequired ?? false,
      defaultRingTimeoutSeconds: sett.data.defaultRingTimeoutSeconds ?? 30,
      voicemailEnabled: sett.data.voicemailEnabled ?? true,
    });
  }, [sett.data, workspace.timezone, workspace.country]);

  if (sett.loading || !form) {
    return <div className="page-inner"><div style={{padding:30, color:"var(--ink-4)"}}>Loading…</div></div>;
  }

  const setF = (k, v) => setForm((f) => ({ ...f, [k]: v }));

  async function save() {
    setSaving(true); setErr(null); setOkMsg(null);
    try {
      const renamed = name !== workspace.name;
      const tzChanged = form.timezone !== workspace.timezone;
      const countryChanged = form.country !== workspace.country;
      if (renamed || tzChanged || countryChanged) {
        await API.workspaces.update(wid, { name, timezone: form.timezone, country: form.country });
      }
      await API.settings.patch(wid, form);
      sett.reload();
      // Reload App-level workspace state so the rename/timezone reflects in
      // the sidebar, breadcrumbs, dashboard timezone, etc. without a refresh.
      if ((renamed || tzChanged || countryChanged) && reloadWorkspaces) {
        await reloadWorkspaces();
      }
      setOkMsg("Saved.");
      setTimeout(() => setOkMsg(null), 1800);
    } catch (err) { setErr(err.message); }
    finally { setSaving(false); }
  }

  return (
    <div className="page-inner" style={{maxWidth: 780}}>
      <div className="row between" style={{alignItems:"flex-start", marginBottom:24}}>
        <div>
          <div className="eyebrow">Account</div>
          <h1 className="page-title" style={{marginTop:6}}>Settings</h1>
          <div className="page-sub">Workspace preferences</div>
        </div>
        <div className="row g8">
          {okMsg && <span style={{color:"var(--good)", fontSize:13, alignSelf:"center"}}>{okMsg}</span>}
          <button className="btn btn-primary" onClick={save} disabled={saving}>{saving ? "Saving…" : "Save changes"}</button>
        </div>
      </div>
      {err && <ErrorChip msg={err}/>}
      <div className="card">
        <div className="card-b col g16">
          <div className="field"><label>Workspace name</label>
            <input className="input" value={name} onChange={(e) => setName(e.target.value)}/>
          </div>
          <div className="field"><label>Timezone</label>
            <select className="select" value={form.timezone} onChange={(e) => setF("timezone", e.target.value)}>
              <option value="America/Los_Angeles">America/Los_Angeles</option>
              <option value="America/Denver">America/Denver</option>
              <option value="America/Chicago">America/Chicago</option>
              <option value="America/New_York">America/New_York</option>
              <option value="Europe/London">Europe/London</option>
              <option value="Europe/Berlin">Europe/Berlin</option>
              <option value="Asia/Tokyo">Asia/Tokyo</option>
            </select>
          </div>
          <div className="field"><label>Default country</label>
            <select className="select" value={form.country} onChange={(e) => setF("country", e.target.value)}>
              <option value="US">United States</option>
              <option value="CA">Canada</option>
              <option value="UK">United Kingdom</option>
              <option value="AU">Australia</option>
            </select>
          </div>
          <div className="field"><label>Default ring timeout (seconds)</label>
            <input className="input" type="number" min="5" max="120" value={form.defaultRingTimeoutSeconds}
              onChange={(e) => setF("defaultRingTimeoutSeconds", parseInt(e.target.value, 10) || 30)}/>
          </div>
          <Toggle label="Two-factor authentication" sub="Required for all owners & admins" value={form.twoFactorRequired} onChange={(v) => setF("twoFactorRequired", v)}/>
          <Toggle label="Call recording consent whisper" sub="Auto-play legal whisper on states that require it" value={form.recordingConsentWhisper} onChange={(v) => setF("recordingConsentWhisper", v)}/>
          <Toggle label="PII redaction in transcripts" sub="Redact credit cards, SSN, DOB from stored text" value={form.piiRedaction} onChange={(v) => setF("piiRedaction", v)}/>
          <Toggle label="Voicemail" sub="Send unanswered calls to voicemail" value={form.voicemailEnabled} onChange={(v) => setF("voicemailEnabled", v)}/>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Billing, WhiteLabel, Integrations, APIKeys, Settings });
