import { useRef as A, useEffect as b, useState as M, useCallback as g } from "react";
import { NylasConnect as B } from "@nylas/connect";
import { BrowserTokenStorage as X, ConfigError as q, MemoryTokenStorage as F, NetworkError as H, NylasConnect as J, NylasConnectError as Q, OAuthError as Y, PopupError as Z, TokenError as ee, isConnectCallback as te, logger as ne, parseConnectCallback as re } from "@nylas/connect";
import { jsx as j } from "react/jsx-runtime";
function v(P) {
  const {
    autoRefreshInterval: u,
    initialLoadingState: k = !0,
    retryAttempts: i = 0,
    enableAutoRecovery: y = !1,
    ...h
  } = P, d = A(null);
  d.current || (d.current = new B(h));
  const s = d.current, C = A({
    isProcessing: !1,
    processedUrl: null,
    hasProcessed: !1
  });
  b(() => {
    const r = globalThis.window?.location.href || "", o = C.current;
    !(r.includes("code=") && r.includes("state=")) && o.hasProcessed && (o.hasProcessed = !1, o.processedUrl = null);
  }), b(() => {
    if (!h.autoHandleCallback)
      return;
    const r = C;
    return (async () => {
      const t = globalThis.window?.location.href || "", e = r.current;
      if (!(e.isProcessing || e.processedUrl === t || e.hasProcessed || !(t.includes("code=") && t.includes("state=")))) {
        try {
          if (await s.getSession()) {
            e.hasProcessed = !0, e.processedUrl = t;
            return;
          }
        } catch {
        }
        e.isProcessing = !0, e.processedUrl = t;
        try {
          if (await s.callback(), e.hasProcessed = !0, globalThis.window?.history?.replaceState) {
            const n = new URL(globalThis.window.location.href), l = ["code", "state", "error", "error_description"];
            let w = !1;
            l.forEach((S) => {
              n.searchParams.has(S) && (n.searchParams.delete(S), w = !0);
            }), w && globalThis.window.history.replaceState(
              globalThis.window.history.state,
              document.title,
              n.toString()
            );
          }
        } catch (n) {
          console.log("callback error", n), e.isProcessing = !1, e.processedUrl = null;
        } finally {
          e.isProcessing = !1;
        }
      }
    })(), () => {
      const t = r.current;
      t?.isProcessing || (t.processedUrl = null, t.hasProcessed = !1);
    };
  }, [s]);
  const [m, c] = M({
    isConnected: !1,
    grant: null,
    isLoading: k,
    error: null
  });
  b(() => {
    let r = !0;
    return (async () => {
      try {
        const t = await s.getSession(), a = await s.getConnectionStatus() === "connected";
        r && c((n) => ({
          ...n,
          isConnected: a,
          grant: t?.grantInfo || null,
          isLoading: !1,
          error: null
        }));
      } catch (t) {
        r && c((e) => ({
          ...e,
          isConnected: !1,
          grant: null,
          isLoading: !1,
          error: t
        }));
      }
    })(), () => {
      r = !1;
    };
  }, [s]), b(() => {
    if (!u || u <= 0)
      return;
    const r = setInterval(async () => {
      try {
        const o = await s.getSession(), e = await s.getConnectionStatus() === "connected";
        c((a) => ({
          ...a,
          isConnected: e,
          grant: o?.grantInfo || null,
          error: null
        }));
      } catch (o) {
        y ? console.debug(
          "Auto-refresh failed, will retry next interval:",
          o
        ) : c((t) => ({
          ...t,
          error: o
        }));
      }
    }, u);
    return () => clearInterval(r);
  }, [s, u, y]), b(() => {
    const r = (t, e, a) => {
      c((n) => {
        switch (t) {
          case "CONNECT_STARTED":
            return {
              ...n,
              isLoading: !0,
              error: null
            };
          case "SIGNED_IN":
          case "SESSION_RESTORED":
            return {
              ...n,
              isConnected: !0,
              grant: e?.grantInfo || null,
              isLoading: !1,
              error: null
            };
          case "SIGNED_OUT":
            return {
              ...n,
              isConnected: !1,
              grant: null,
              isLoading: !1,
              error: null
            };
          case "CONNECT_ERROR":
          case "NETWORK_ERROR":
          case "TOKEN_VALIDATION_ERROR":
            return {
              ...n,
              isLoading: !1,
              error: a?.error || new Error("Authentication error")
            };
          case "CONNECT_CANCELLED":
            return {
              ...n,
              isLoading: !1,
              error: null
            };
          case "SESSION_EXPIRED":
          case "SESSION_INVALID":
            return {
              ...n,
              isConnected: !1,
              grant: null,
              isLoading: !1,
              error: null
            };
          default:
            return n;
        }
      });
    };
    return s.onConnectStateChange(
      r
    );
  }, [s]);
  const N = g(
    async (r = {}) => {
      c((e) => ({ ...e, isLoading: !0, error: null }));
      let o;
      const t = i + 1;
      for (let e = 1; e <= t; e++)
        try {
          return await s.connect(r);
        } catch (a) {
          if (o = a, e < t) {
            const n = Math.min(1e3 * Math.pow(2, e - 1), 5e3);
            await new Promise((l) => setTimeout(l, n));
          }
        }
      throw o;
    },
    [s, i]
  ), E = g(
    async (r) => {
      c((e) => ({ ...e, isLoading: !0, error: null }));
      let o;
      const t = i + 1;
      for (let e = 1; e <= t; e++)
        try {
          await s.logout(r);
          return;
        } catch (a) {
          if (o = a, e < t) {
            const n = Math.min(1e3 * Math.pow(2, e - 1), 3e3);
            await new Promise((l) => setTimeout(l, n));
          }
        }
      throw c((e) => ({
        ...e,
        isLoading: !1,
        error: o
      })), o;
    },
    [s, i]
  ), L = g(async () => {
    c((t) => ({ ...t, isLoading: !0, error: null }));
    let r;
    const o = i + 1;
    for (let t = 1; t <= o; t++)
      try {
        const e = await s.getSession(), n = await s.getConnectionStatus() === "connected";
        c((l) => ({
          ...l,
          isConnected: n,
          grant: e?.grantInfo || null,
          isLoading: !1,
          error: null
        }));
        return;
      } catch (e) {
        if (r = e, t < o) {
          const a = Math.min(1e3 * Math.pow(2, t - 1), 3e3);
          await new Promise((n) => setTimeout(n, a));
        }
      }
    throw c((t) => ({
      ...t,
      isConnected: !1,
      grant: null,
      isLoading: !1,
      error: r
    })), r;
  }, [s, i]), T = g(
    (r) => s.onConnectStateChange(r),
    [s]
  ), R = g(
    (r) => {
      s.setLogLevel(r);
    },
    [s]
  );
  return {
    // State
    ...m,
    // Actions
    connect: N,
    logout: E,
    refreshSession: L,
    subscribe: T,
    // Logger controls
    setLogLevel: R,
    // Direct access
    connectClient: s
  };
}
function V({
  clientId: P,
  redirectUri: u,
  apiUrl: k,
  defaultScopes: i,
  persistTokens: y,
  method: h = "inline",
  provider: d,
  scopes: s,
  loginHint: C,
  popupWidth: m,
  popupHeight: c,
  text: N = "Connect your inbox",
  className: E,
  style: L,
  disabled: T,
  // styling
  variant: R = "primary",
  size: r = "md",
  unstyled: o = !1,
  cssVars: t,
  // advanced config
  identityProviderToken: e,
  codeExchange: a,
  onStart: n,
  onSuccess: l,
  onError: w,
  onCancel: S,
  children: U
}) {
  const { connect: p, isLoading: O } = v({
    clientId: P,
    redirectUri: u,
    apiUrl: k,
    // Only pass defaultScopes if caller provides it to override defaults
    ...i ? { defaultScopes: i } : {},
    persistTokens: y,
    autoHandleCallback: !0,
    identityProviderToken: e,
    codeExchange: a
  }), _ = g(async () => {
    try {
      n?.();
      const f = await p({
        method: h,
        provider: d,
        scopes: s,
        loginHint: C,
        popupWidth: m,
        popupHeight: c
      });
      if (typeof f == "string") {
        window.location.assign(f);
        return;
      }
      l?.(f);
    } catch (f) {
      const I = f?.message || "";
      if (I.includes("closed") || I.includes("cancelled")) {
        S?.(I);
        return;
      }
      w?.(f);
    }
  }, [
    p,
    h,
    d,
    s,
    C,
    m,
    c,
    n,
    l,
    S,
    w
  ]), x = o ? E : ["nylas-btn", `nylas-btn--${R}`, `nylas-btn--${r}`, E].filter(Boolean).join(" "), D = t ? { ...t, ...L } : L;
  return /* @__PURE__ */ j(
    "button",
    {
      type: "button",
      className: x,
      style: D,
      disabled: T || O,
      "aria-busy": O || void 0,
      onClick: _,
      children: U ?? N
    }
  );
}
export {
  X as BrowserTokenStorage,
  q as ConfigError,
  F as MemoryTokenStorage,
  H as NetworkError,
  J as NylasConnect,
  V as NylasConnectButton,
  Q as NylasConnectError,
  Y as OAuthError,
  Z as PopupError,
  ee as TokenError,
  te as isConnectCallback,
  ne as logger,
  re as parseConnectCallback,
  v as useNylasConnect
};
//# sourceMappingURL=connect.js.map
