// Settings panel — account info + BYO AI provider key.
//
// BYO keys default to sessionStorage so they clear when the browser session
// ends. Users can explicitly opt into localStorage for this device. Server-
// side, /api/* routes prefer the request-body key over the env key (see
// lib/openai.js getClientForRequest); handlers never persist the key.

const PL_BYO_KEY_LEGACY = "pl.byoApiKey";
const PL_BYO_KEY_PREFIX = "pl.byoApiKey.";
const PL_BYO_PROVIDER = "pl.byoProvider";

function safeStorageRead(storage, key) {
  if (!storage) return "";
  try { return storage.getItem(key) || ""; } catch { return ""; }
}
function safeStorageWrite(storage, key, value) {
  if (!storage) return;
  try {
    if (!value) storage.removeItem(key);
    else storage.setItem(key, value);
  } catch {}
}
function getStorage(kind) {
  try { return kind === "session" ? window.sessionStorage : window.localStorage; } catch { return null; }
}
function normalizeByoProvider(provider) {
  return provider === "anthropic" ? "anthropic" : "openai";
}
function byoKeyStorageKey(provider) {
  return `${PL_BYO_KEY_PREFIX}${normalizeByoProvider(provider)}`;
}
function readByoProvider() {
  const sessionProvider = safeStorageRead(getStorage("session"), PL_BYO_PROVIDER);
  const deviceProvider = safeStorageRead(getStorage("device"), PL_BYO_PROVIDER);
  if (sessionProvider || deviceProvider) return normalizeByoProvider(sessionProvider || deviceProvider);
  return "openai";
}
function providerName(provider) {
  return normalizeByoProvider(provider) === "anthropic" ? "Anthropic" : "OpenAI";
}
function readSessionByoKey(provider = readByoProvider()) {
  const p = normalizeByoProvider(provider);
  return safeStorageRead(getStorage("session"), byoKeyStorageKey(p)) ||
    (p === "openai" ? safeStorageRead(getStorage("session"), PL_BYO_KEY_LEGACY) : "");
}
function readDeviceByoKey(provider = readByoProvider()) {
  const p = normalizeByoProvider(provider);
  return safeStorageRead(getStorage("device"), byoKeyStorageKey(p)) ||
    (p === "openai" ? safeStorageRead(getStorage("device"), PL_BYO_KEY_LEGACY) : "");
}
function readByoKey(provider = readByoProvider()) { return readSessionByoKey(provider) || readDeviceByoKey(provider); }
function writeByoKey(k, { persist = false, provider = readByoProvider() } = {}) {
  const p = normalizeByoProvider(provider);
  const keyName = byoKeyStorageKey(p);
  if (!k) {
    safeStorageWrite(getStorage("session"), keyName, "");
    safeStorageWrite(getStorage("device"), keyName, "");
    if (p === "openai") {
      safeStorageWrite(getStorage("session"), PL_BYO_KEY_LEGACY, "");
      safeStorageWrite(getStorage("device"), PL_BYO_KEY_LEGACY, "");
    }
    return;
  }
  if (persist) {
    safeStorageWrite(getStorage("device"), keyName, k);
    safeStorageWrite(getStorage("device"), PL_BYO_PROVIDER, p);
    safeStorageWrite(getStorage("session"), keyName, "");
    safeStorageWrite(getStorage("session"), PL_BYO_PROVIDER, "");
  } else {
    safeStorageWrite(getStorage("session"), keyName, k);
    safeStorageWrite(getStorage("session"), PL_BYO_PROVIDER, p);
    safeStorageWrite(getStorage("device"), keyName, "");
    safeStorageWrite(getStorage("device"), PL_BYO_PROVIDER, "");
  }
}
function byoKeyStorageKind(provider = readByoProvider()) {
  if (readSessionByoKey(provider)) return "session";
  if (readDeviceByoKey(provider)) return "device";
  return "none";
}

window.ByoKey = {
  read: readByoKey,
  provider: readByoProvider,
  providerName: () => providerName(readByoProvider()),
  write: writeByoKey,
  remove: (provider = readByoProvider()) => writeByoKey("", { provider }),
  isSet: (provider = readByoProvider()) => !!readByoKey(provider),
  storageKind: byoKeyStorageKind,
  requestFields: () => ({
    provider: readByoProvider(),
    apiKey: readByoKey() || null,
  }),
};

const { useState: useStateSet, useEffect: useEffectSet } = React;

// Official single-color brand glyphs (Simple Icons, 24x24 viewBox). Rendered in
// white on each provider's brand-colored tile.
const PROVIDER_LOGOS = {
  openai: "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z",
  anthropic: "M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z",
  azure: "M22.379 23.343a1.62 1.62 0 0 0 1.536-2.14v.002L17.35 1.76A1.62 1.62 0 0 0 15.816.657H8.184A1.62 1.62 0 0 0 6.65 1.76L.086 21.204a1.62 1.62 0 0 0 1.536 2.139h4.741a1.62 1.62 0 0 0 1.535-1.103l.977-2.892 4.947 3.675c.28.208.618.32.966.32m-3.084-12.531 3.624 10.739a.54.54 0 0 1-.51.713v-.001h-.03a.54.54 0 0 1-.322-.106l-9.287-6.9h4.853m6.313 7.006c.116-.326.13-.694.007-1.058L9.79 1.76a1.722 1.722 0 0 0-.007-.02h6.034a.54.54 0 0 1 .512.366l6.562 19.445a.54.54 0 0 1-.338.684",
  google: "M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z",
};

const AI_PROVIDERS = [
  {
    id: "openai",
    name: "OpenAI",
    tagline: "GPT-5.5 · GPT-5.4-mini",
    mark: "AI",
    markStyle: { background: "#10A37F", color: "white" },
    status: "ready",
    keyPrefix: "sk-…",
    description: "OpenAI API using your key, your account, your billing.",
  },
  {
    id: "anthropic",
    name: "Anthropic",
    tagline: "Claude Opus 4.8 · Sonnet 4.6",
    mark: "AN",
    markStyle: { background: "#D97757", color: "white" },
    status: "ready",
    keyPrefix: "sk-ant-…",
    description: "Claude family. Use your existing Anthropic workspace key.",
  },
  {
    id: "azure",
    name: "Microsoft Azure",
    tagline: "Azure OpenAI · Copilot stack",
    mark: "AZ",
    markStyle: { background: "#0078D4", color: "white" },
    status: "enterprise",
    description: "Run on your Azure tenant — same compliance posture as Microsoft 365 Copilot.",
  },
  {
    id: "google",
    name: "Google Vertex AI",
    tagline: "Gemini 2.5 family",
    mark: "GO",
    markStyle: { background: "#1A73E8", color: "white" },
    status: "enterprise",
    description: "Run on Vertex AI inside your GCP project.",
  },
];

function ProviderCard({ provider, selected, onSelect }) {
  return (
    <button
      type="button"
      className={`provider-card ${selected ? "is-selected" : ""}`}
      onClick={() => onSelect(provider.id)}
    >
      <div className="provider-card-head">
        <span className="provider-mark" style={provider.markStyle}>
          {PROVIDER_LOGOS[provider.id] ? (
            <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" aria-hidden="true">
              <path d={PROVIDER_LOGOS[provider.id]}/>
            </svg>
          ) : provider.mark}
        </span>
        <span className={`provider-status provider-status-${provider.status}`}>
          {provider.status === "ready" ? "Available now" : "Enterprise"}
        </span>
      </div>
      <div className="provider-name">{provider.name}</div>
      <div className="provider-tagline">{provider.tagline}</div>
      <div className="provider-desc">{provider.description}</div>
    </button>
  );
}

function SettingsScreen({ user, onClose, onSignOut, byoKeyStatus, creditStatus, aiAccess = {}, onByoKeyChange }) {
  const [provider, setProvider] = useStateSet(readByoProvider());
  const [keyInput, setKeyInput] = useStateSet(() => readByoKey(readByoProvider()));
  const [persistKey, setPersistKey] = useStateSet(() => byoKeyStorageKind(readByoProvider()) === "device");
  const [reveal, setReveal] = useStateSet(false);
  const [status, setStatus] = useStateSet(null);
  const [busy, setBusy] = useStateSet(false);
  const selectedProvider = AI_PROVIDERS.find(p => p.id === provider) || AI_PROVIDERS[0];
  const companyManaged = aiAccess?.mode === "company_managed" || user?.aiAccessMode === "company_managed";
  const allowUserKeys = !companyManaged && aiAccess?.allowUserKeys !== false && user?.allowUserKeys !== false;
  const managedCompanyName = user?.companyLicenseName || aiAccess?.companyName || user?.company || "your organization";

  useEffectSet(() => {
    setKeyInput(readByoKey(provider));
    setPersistKey(byoKeyStorageKind(provider) === "device");
    setStatus(null);
    setReveal(false);
  }, [provider]);

  async function validateAndSave() {
    if (!keyInput.trim()) {
      setStatus({ kind: "error", message: "Paste a key before saving." });
      return;
    }
    setBusy(true);
    setStatus({ kind: "info", message: `Checking your key with ${selectedProvider.name}…` });
    try {
      const resp = await fetch("/api/validate-key", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ provider, apiKey: keyInput.trim() }),
      });
      const data = await resp.json();
      if (!data.valid) {
        setStatus({ kind: "error", message: data.error || `${selectedProvider.name} rejected this key.` });
      } else {
        writeByoKey(keyInput.trim(), { provider, persist: persistKey });
        onByoKeyChange();
        setStatus({
          kind: "ok",
          message: persistKey
            ? `Key validated and remembered on this device. Requests are routed through this app backend, then billed to your ${selectedProvider.name} account.`
            : "Key validated for this browser session. It will clear when this session ends.",
        });
      }
    } catch (err) {
      setStatus({ kind: "error", message: "Couldn't reach the validator. Check your network and try again." });
    } finally {
      setBusy(false);
    }
  }

  function removeKey() {
    window.ByoKey.remove(provider);
    setKeyInput("");
    onByoKeyChange();
    setStatus({ kind: "info", message: "Removed. Platform credits will be used until you add your own key." });
  }

  async function clearSavedCases() {
    try {
      const deleted = await window.Workspace.clearCases();
      setStatus({ kind: "info", message: `${deleted} saved ${deleted === 1 ? "case was" : "cases were"} cleared from your encrypted workspace.` });
    } catch (err) {
      setStatus({ kind: "error", message: err.message || "Couldn't clear saved cases." });
    }
  }

  return (
    <div className="screen settings-screen">
      <AppTopBar user={user} active="settings" onNewCase={null} onOpenSettings={null} onSignOut={onSignOut} byoKeyStatus={byoKeyStatus} creditStatus={creditStatus}/>

      <main className="settings-main">
        <div className="settings-head">
          <button className="btn-ghost" onClick={onClose}>
            <IconText name="arrow-left">Back to workspace</IconText>
          </button>
          <h1 className="display">Settings</h1>
        </div>

        {!companyManaged && creditStatus && (
          <section className="settings-section">
            <div className="settings-section-head">
              <h2 className="display-sm">Plan &amp; credits</h2>
              <div className="key-pill key-pill-ok" style={{ textTransform: "capitalize" }}>
                <Icon name="shield-check" size={14}/>
                <span>{creditStatus.plan || "free"} plan</span>
              </div>
            </div>
            <p className="lede">
              {Math.floor(creditStatus.remaining)} credits available now
              {creditStatus.replenishesAt
                ? ` · refreshes ${new Date(creditStatus.replenishesAt).toLocaleDateString()}`
                : ""}.
              {creditStatus.grantRemaining > 0
                ? ` Includes ${Math.floor(creditStatus.grantRemaining)} one-time welcome credits.`
                : ""}
            </p>
            <button className="btn-primary" onClick={() => window.dispatchEvent(new CustomEvent("cabl:open-pricing"))}>
              <IconText name="coins">View plans &amp; upgrade</IconText>
            </button>
          </section>
        )}

        <section className="settings-section">
          <div className="settings-section-head">
            <h2 className="display-sm">AI provider</h2>
            <div className={`key-pill key-pill-${byoKeyStatus.kind}`}>
              <Icon name={byoKeyStatus.kind === "ok" ? "key-round" : "lock"} size={14}/>
              <span>{byoKeyStatus.label}</span>
            </div>
          </div>

          {!allowUserKeys ? (
            <>
              <p className="lede">
                {managedCompanyName} manages AI access for this workspace. You do not need to paste a key,
                choose a model, or manage credits to use the app.
              </p>
              <div className="provider-enterprise-panel">
                <div className="kicker">Company-managed access</div>
                <p>
                  CABL routes AI requests through the provider setup approved for your organization.
                  Billing, seats, provider choice, and tenant configuration are handled before employees are invited.
                </p>
                <ul>
                  <li>No personal API key is required.</li>
                  <li>Employees cannot switch provider keys from the app.</li>
                  <li>Admins can configure SSO, seat counts, and provider tenancy with CABL.</li>
                </ul>
              </div>
            </>
          ) : (
            <>
              <p className="lede">
                By default, the platform is secured, encrypted, and ready to use.
                <br/><br/>
                Teams with specific privacy, security, or compliance requirements can also connect their own
                AI provider account for added control.
                <br/><br/>
                Choose the provider you want to use, enter your credentials, and the platform will send your
                chat, research, and planning requests through that provider using your account.
                <br/><br/>
                Your key is only used to send the request. It is not stored on our servers.
              </p>

              <div className="provider-grid">
                {AI_PROVIDERS.map(p => (
                  <ProviderCard
                    key={p.id}
                    provider={p}
                    selected={provider === p.id}
                    onSelect={setProvider}
                  />
                ))}
              </div>

              <div className="provider-other">
                Need something else? <strong>Self-hosted</strong> (Ollama, vLLM, AWS Bedrock, on-prem GPU)
                is supported on Enterprise — talk to us.
              </div>

              {selectedProvider.status === "ready" ? (
                <>
              <div className="settings-key-row">
                <input
                  type={reveal ? "text" : "password"}
                  className="settings-key-input"
                  placeholder={selectedProvider.keyPrefix || "API key"}
                  value={keyInput}
                  onChange={e => setKeyInput(e.target.value)}
                  autoComplete="off"
                  spellCheck="false"
                />
                <button type="button" className="btn-ghost" onClick={() => setReveal(r => !r)}>
                  <IconText name={reveal ? "eye-off" : "eye"}>{reveal ? "Hide" : "Show"}</IconText>
                </button>
              </div>

              <label className="auth-microcopy" style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 10 }}>
                <input
                  type="checkbox"
                  checked={persistKey}
                  onChange={e => setPersistKey(e.target.checked)}
                />
                Remember this key on this device. Leave unchecked to keep it for this browser session only.
              </label>

              <div className="settings-key-actions">
                <button className="btn-primary" disabled={busy} onClick={validateAndSave}>
                  <IconText name={busy ? "rotate-cw" : "check"}>{busy ? "Checking..." : "Validate & save"}</IconText>
                </button>
                {window.ByoKey.isSet(provider) && (
                  <button className="btn-ghost" onClick={removeKey}>
                    <IconText name="trash">Remove key</IconText>
                  </button>
                )}
              </div>

              {status && <div className={`settings-status settings-status-${status.kind}`}>{status.message}</div>}
                </>
              ) : (
                <div className="provider-enterprise-panel">
                  <div className="kicker">Enterprise integration</div>
                  <p>
                    {selectedProvider.name} is available on our Enterprise plan.
                    We'll provision a tenant-scoped connector wired to your account (workspace key, Azure
                    deployment, or Vertex service account) so negotiation traffic stays inside your
                    provider's compliance perimeter.
                  </p>
                  <ul>
                    <li>SSO + SCIM provisioning across your identity provider</li>
                    <li>Data residency honored by the provider you select</li>
                    <li>Per-seat usage reporting and budget caps</li>
                    <li>BAA / DPA available on request</li>
                  </ul>
                  <button type="button" className="btn-primary" disabled>
                    Contact sales to enable {selectedProvider.name}
                  </button>
                </div>
              )}
            </>
          )}

          <div className="settings-privacy-note">
            <div className="kicker">Privacy</div>
            <ul>
              <li>We do not store uploaded files{allowUserKeys ? " or API keys" : ""}.</li>
              <li>Saved cases are encrypted.</li>
              <li>During coaching, only the information needed to generate your response is sent to {allowUserKeys ? "your selected AI provider" : "the company-approved AI provider"}.</li>
            </ul>
          </div>
        </section>

        <section className="settings-section">
          <h2 className="display-sm">Account</h2>
          <dl className="settings-account">
            <div><dt>Full name</dt><dd>{user.fullName}</dd></div>
            <div><dt>Work email</dt><dd>{user.email}</dd></div>
            <div><dt>Company</dt><dd>{user.company}</dd></div>
          </dl>
          <div className="settings-key-actions">
            <button className="btn-ghost" onClick={clearSavedCases}>
              <IconText name="trash">Clear saved cases</IconText>
            </button>
            <button className="btn-ghost" onClick={onSignOut}>
              <IconText name="log-out">Sign out of this device</IconText>
            </button>
          </div>
        </section>
      </main>
    </div>
  );
}

window.SettingsScreen = SettingsScreen;
