import { resolveStaleTime as o, functionalUpdate as y, noop as a, hashKey as c, partialMatchKey as f, hashQueryKeyByOptions as m, skipToken as p } from "./utils.js";
import { QueryCache as Q } from "./queryCache.js";
import { MutationCache as O } from "./mutationCache.js";
import { focusManager as v } from "./focusManager.js";
import { onlineManager as l } from "./onlineManager.js";
import { notifyManager as u } from "./notifyManager.js";
import { infiniteQueryBehavior as d } from "./infiniteQueryBehavior.js";
var P = class {
  #e;
  #t;
  #r;
  #i;
  #a;
  #s;
  #u;
  #n;
  constructor(e = {}) {
    this.#e = e.queryCache || new Q(), this.#t = e.mutationCache || new O(), this.#r = e.defaultOptions || {}, this.#i = /* @__PURE__ */ new Map(), this.#a = /* @__PURE__ */ new Map(), this.#s = 0;
  }
  mount() {
    this.#s++, this.#s === 1 && (this.#u = v.subscribe(async (e) => {
      e && (await this.resumePausedMutations(), this.#e.onFocus());
    }), this.#n = l.subscribe(async (e) => {
      e && (await this.resumePausedMutations(), this.#e.onOnline());
    }));
  }
  unmount() {
    this.#s--, this.#s === 0 && (this.#u?.(), this.#u = void 0, this.#n?.(), this.#n = void 0);
  }
  isFetching(e) {
    return this.#e.findAll({ ...e, fetchStatus: "fetching" }).length;
  }
  isMutating(e) {
    return this.#t.findAll({ ...e, status: "pending" }).length;
  }
  /**
   * Imperative (non-reactive) way to retrieve data for a QueryKey.
   * Should only be used in callbacks or functions where reading the latest data is necessary, e.g. for optimistic updates.
   *
   * Hint: Do not use this function inside a component, because it won't receive updates.
   * Use `useQuery` to create a `QueryObserver` that subscribes to changes.
   */
  getQueryData(e) {
    const t = this.defaultQueryOptions({ queryKey: e });
    return this.#e.get(t.queryHash)?.state.data;
  }
  ensureQueryData(e) {
    const t = this.defaultQueryOptions(e), r = this.#e.build(this, t), s = r.state.data;
    return s === void 0 ? this.fetchQuery(e) : (e.revalidateIfStale && r.isStaleByTime(o(t.staleTime, r)) && this.prefetchQuery(t), Promise.resolve(s));
  }
  getQueriesData(e) {
    return this.#e.findAll(e).map(({ queryKey: t, state: r }) => {
      const s = r.data;
      return [t, s];
    });
  }
  setQueryData(e, t, r) {
    const s = this.defaultQueryOptions({ queryKey: e }), n = this.#e.get(
      s.queryHash
    )?.state.data, h = y(t, n);
    if (h !== void 0)
      return this.#e.build(this, s).setData(h, { ...r, manual: !0 });
  }
  setQueriesData(e, t, r) {
    return u.batch(
      () => this.#e.findAll(e).map(({ queryKey: s }) => [
        s,
        this.setQueryData(s, t, r)
      ])
    );
  }
  getQueryState(e) {
    const t = this.defaultQueryOptions({ queryKey: e });
    return this.#e.get(
      t.queryHash
    )?.state;
  }
  removeQueries(e) {
    const t = this.#e;
    u.batch(() => {
      t.findAll(e).forEach((r) => {
        t.remove(r);
      });
    });
  }
  resetQueries(e, t) {
    const r = this.#e;
    return u.batch(() => (r.findAll(e).forEach((s) => {
      s.reset();
    }), this.refetchQueries(
      {
        type: "active",
        ...e
      },
      t
    )));
  }
  cancelQueries(e, t = {}) {
    const r = { revert: !0, ...t }, s = u.batch(
      () => this.#e.findAll(e).map((i) => i.cancel(r))
    );
    return Promise.all(s).then(a).catch(a);
  }
  invalidateQueries(e, t = {}) {
    return u.batch(() => (this.#e.findAll(e).forEach((r) => {
      r.invalidate();
    }), e?.refetchType === "none" ? Promise.resolve() : this.refetchQueries(
      {
        ...e,
        type: e?.refetchType ?? e?.type ?? "active"
      },
      t
    )));
  }
  refetchQueries(e, t = {}) {
    const r = {
      ...t,
      cancelRefetch: t.cancelRefetch ?? !0
    }, s = u.batch(
      () => this.#e.findAll(e).filter((i) => !i.isDisabled() && !i.isStatic()).map((i) => {
        let n = i.fetch(void 0, r);
        return r.throwOnError || (n = n.catch(a)), i.state.fetchStatus === "paused" ? Promise.resolve() : n;
      })
    );
    return Promise.all(s).then(a);
  }
  fetchQuery(e) {
    const t = this.defaultQueryOptions(e);
    t.retry === void 0 && (t.retry = !1);
    const r = this.#e.build(this, t);
    return r.isStaleByTime(
      o(t.staleTime, r)
    ) ? r.fetch(t) : Promise.resolve(r.state.data);
  }
  prefetchQuery(e) {
    return this.fetchQuery(e).then(a).catch(a);
  }
  fetchInfiniteQuery(e) {
    return e.behavior = d(e.pages), this.fetchQuery(e);
  }
  prefetchInfiniteQuery(e) {
    return this.fetchInfiniteQuery(e).then(a).catch(a);
  }
  ensureInfiniteQueryData(e) {
    return e.behavior = d(e.pages), this.ensureQueryData(e);
  }
  resumePausedMutations() {
    return l.isOnline() ? this.#t.resumePausedMutations() : Promise.resolve();
  }
  getQueryCache() {
    return this.#e;
  }
  getMutationCache() {
    return this.#t;
  }
  getDefaultOptions() {
    return this.#r;
  }
  setDefaultOptions(e) {
    this.#r = e;
  }
  setQueryDefaults(e, t) {
    this.#i.set(c(e), {
      queryKey: e,
      defaultOptions: t
    });
  }
  getQueryDefaults(e) {
    const t = [...this.#i.values()], r = {};
    return t.forEach((s) => {
      f(e, s.queryKey) && Object.assign(r, s.defaultOptions);
    }), r;
  }
  setMutationDefaults(e, t) {
    this.#a.set(c(e), {
      mutationKey: e,
      defaultOptions: t
    });
  }
  getMutationDefaults(e) {
    const t = [...this.#a.values()], r = {};
    return t.forEach((s) => {
      f(e, s.mutationKey) && Object.assign(r, s.defaultOptions);
    }), r;
  }
  defaultQueryOptions(e) {
    if (e._defaulted)
      return e;
    const t = {
      ...this.#r.queries,
      ...this.getQueryDefaults(e.queryKey),
      ...e,
      _defaulted: !0
    };
    return t.queryHash || (t.queryHash = m(
      t.queryKey,
      t
    )), t.refetchOnReconnect === void 0 && (t.refetchOnReconnect = t.networkMode !== "always"), t.throwOnError === void 0 && (t.throwOnError = !!t.suspense), !t.networkMode && t.persister && (t.networkMode = "offlineFirst"), t.queryFn === p && (t.enabled = !1), t;
  }
  defaultMutationOptions(e) {
    return e?._defaulted ? e : {
      ...this.#r.mutations,
      ...e?.mutationKey && this.getMutationDefaults(e.mutationKey),
      ...e,
      _defaulted: !0
    };
  }
  clear() {
    this.#e.clear(), this.#t.clear();
  }
};
export {
  P as QueryClient
};
