import { INTERNAL_EVT_SESSION_REFRESHING_START as c, INTERNAL_EVT_SESSION_READY as A, INTERNAL_EVT_SESSION_REFRESHING_END as y } from "./constants.js";
import { EVT_SESSION_EXPIRED as O, ERR_SESSION_REFRESH_ABORTED as T, ERR_SESSION_FACTORY_UNAVAILABLE as p, ERR_SESSION_INVALID as u } from "../constants.js";
import { createEventEmitter as d } from "../../../reactive/eventEmitter/main.js";
import { createPromisor as F } from "../../../async/promisor/main.js";
import { ALREADY_RESOLVED_PROMISE as L } from "../../../../utils/async/constants.js";
import { struct as l } from "../../../../utils/struct/main.js";
import { getter as o, enumerable as s } from "../../../../utils/struct/property.js";
import { isAbortSignal as P, abortSignalForAny as w } from "../../../../utils/abort/main.js";
import { tryResolve as D } from "../../../../utils/async/main.js";
import { isFunction as V } from "../../../../utils/value/is.js";
const U = (R, i) => {
  let _ = !1, n, t, f = !0, S;
  const a = /* @__PURE__ */ Symbol("<next_session>"), E = d();
  function N(e) {
    try {
      i.assert?.(e);
    } catch {
      throw u;
    }
  }
  function h(e) {
    if (!V(e)) throw p;
  }
  const m = F((e, r) => {
    if (!t) t = e;
    else return I(P(r) ? w([r, e]) : e);
  }), I = async (e) => {
    let r = a;
    try {
      _ = !1, t = e, f && await (n ??= (async () => {
        await L, f = !1, E.emit(c);
      })()), h(i.onRefresh), r = await D(() => i.onRefresh(S, e)).finally(() => {
        if (e.aborted) throw T;
      });
    } finally {
      if (t === e)
        try {
          r !== a && (N(r), S = r, E.emit(A));
        } finally {
          n = void 0, f = !0, E.emit(y);
        }
    }
  };
  return R.on(O, () => _ = !n), m(), l({
    context: s(
      l({
        emitter: s(R),
        specification: s(i)
      })
    ),
    on: s(E.on),
    pending: o(() => _),
    promise: o(() => m.promise),
    refresh: s(m.bind(void 0)),
    refreshing: o(() => !!n),
    session: o(() => S),
    signal: o(() => t)
  });
};
export {
  U as createSessionRefresher
};
