import { jsxs as J, jsx as E } from "react/jsx-runtime";
import h from "prop-types";
import Q from "lodash/isUndefined";
import { use as Z, createContext as ee } from "react";
import l from "@arcblock/ux/lib/Toast";
import { useReactive as v, useMemoizedFn as u, useCreation as te, useLatest as oe } from "ahooks";
import O from "lodash/noop";
import B from "lodash/omit";
import { joinURL as re } from "ufo";
import { translate as ne } from "@arcblock/ux/lib/Locale/util";
import ie from "@arcblock/ux/lib/Dialog/use-confirm";
import { getBlockletData as S, getFederatedEnabled as C, getMaster as k } from "@arcblock/ux/lib/Util/federated";
import { BLOCKLET_SERVICE_PATH_PREFIX as F, LOGIN_PROVIDER_NAME as f } from "@arcblock/ux/lib/Util/constant";
import { createAxios as se, openPopup as ae, runPopup as de, sleep as ce, getApiErrorMessage as m } from "../utils.js";
import { parseResponse as ue, PassportSwitcher as le } from "../components/PassportSwitcher.js";
import pe from "../Session/hooks/use-mobile.js";
import he from "./bind-conflict-alert.js";
const D = ee({}), { Provider: fe, Consumer: Te } = D, R = `${F}/api/oauth`, be = {
  zh: {
    bindOAuth: "绑定第三方登录",
    bind: "绑定",
    noneOAuth: "未配置第三方登录方式",
    bindOAuthSucceed: "绑定 {provider} 成功",
    unbindOAuthSucceed: "解绑 {provider} 成功",
    loginOAuthFailed: "登录 {provider} 失败",
    bindOAuthFailed: "绑定 {provider} 失败",
    unbindOAuthFailed: "绑定 {provider} 失败",
    loginRequired: "授权请求被拒绝",
    cancelAuth: "取消授权",
    noPassports: "没有可更换的通行证",
    confirm: "我知道了",
    ALREADY_EXIST: "当前账户已存在",
    ALREADY_BIND: "当前账户绑定过 {provider}"
  },
  en: {
    bindOAuth: "Bind third party login",
    bind: "Bind ",
    noneOAuth: "Third party login is not configured",
    bindOAuthSucceed: "Bind {provider} succeed",
    unbindOAuthSucceed: "Unbind {provider} succeed",
    loginOAuthFailed: "Login {provider} failed",
    bindOAuthFailed: "Bind {provider} failed",
    unbindOAuthFailed: "Unbind {provider} failed",
    loginRequired: "You have declined the authentication request",
    cancelAuth: "Cancel authentication",
    noPassports: "No passports to switch",
    confirm: "I know",
    ALREADY_EXIST: "Your account already exists",
    ALREADY_BIND: "Your account is already bind to {provider}"
  }
};
function Ae({
  children: w,
  locale: p = "en",
  onBindOAuth: T = O,
  onUnbindOAuth: _ = O,
  onSwitchPassport: I = O,
  session: Y = null
}) {
  const x = pe(), { confirmApi: M, confirmHolder: j } = ie({
    maxWidth: !1,
    PaperProps: {
      style: {
        minWidth: x ? "100%" : 600
      }
    }
  }), r = v({
    baseUrl: "/",
    bindFnSession: void 0,
    bindAuthLoading: !1,
    unbindAuthLoading: !1
  }), c = v({
    open: !1,
    currentUser: null,
    passports: [],
    selectedPassport: void 0,
    reset() {
      c.open = !1, c.currentUser = null, c.passports = [], c.selectedPassport = void 0;
    }
  }), b = v({
    user: null,
    // loginLoading: false,
    checking: !1,
    loading: !1,
    error: "",
    status: "",
    // scanned, succeed, error
    reset({ status: t = "" } = {}) {
      b.loading = !!t, b.checking = !1, b.error = "", b.status = t;
    }
  }), d = u((t, e = {}) => ne(be, t, p, "en", e)), N = te(() => se({
    // NOTICE: 请求必须向当前站点发起
    baseURL: R
  }), [r.baseUrl, R]), A = oe(N), P = u(async () => {
    if (r.baseUrl === "/")
      return window.blocklet;
    try {
      if (new URL(r.baseUrl).host === window.location.host)
        return window.blocklet;
    } catch {
    }
    return await S(r.baseUrl);
  }), U = u(async ({ sourceAppPid: t } = {}) => {
    const e = await P(), o = C(e), n = k(e);
    let i = {};
    return o && n?.appPid && t === n?.appPid ? i = (await S(n.appUrl))?.settings?.authentication || {} : i = e?.settings?.authentication || {}, Object.keys(i).reduce((a, s) => (i[s]?.type === "oauth" && (a[s] = i[s]), a), {});
  }), X = u(async ({ sourceAppPid: t } = {}) => {
    const e = await U({ sourceAppPid: t });
    return Object.entries(e).map(([n, i]) => ({ ...i, provider: n })).filter((n) => n.enabled).sort((n, i) => n?.order !== void 0 && i?.order !== void 0 ? n.order - i.order : n?.order !== void 0 ? -1 : 1);
  }), L = u(async ({ provider: t } = {}) => {
    const e = ae(re(r.baseUrl, F, "/oauth/login", t), {
      name: "oauth-login:popup",
      offsetX: 650,
      height: 700,
      width: 500
    });
    try {
      const o = await de({
        popup: e,
        closeTimeout: 1500
      });
      return o?.response ? o.response?.code : null;
    } catch (o) {
      throw o?.message === "Popup closed" ? new Error(d("cancelAuth")) : o;
    }
  }), q = async ({ session: t, oauthItem: e } = {}) => {
    r.bindFnSession = t, r.bindAuthLoading = !0;
    try {
      const o = await L(e), n = r.bindFnSession?.user?.sourceAppPid;
      await A.current.post("/bind", {
        locale: p,
        provider: e.provider,
        code: o,
        sourceAppPid: n
      }), l.success(d("bindOAuthSucceed", { provider: f[e.provider] })), T(e);
    } catch (o) {
      if (o.response?.status === 409) {
        const { data: i = {} } = o.response || {}, { code: a } = i || {};
        ["ALREADY_EXIST", "ALREADY_BIND"].includes(a) ? M.open({
          title: d(a, { provider: e.provider }),
          showCancelButton: !1,
          confirmButtonText: d("confirm"),
          content: /* @__PURE__ */ E(he, { data: i }),
          onConfirm(s) {
            s();
          }
        }) : l.error(
          m(o, d("bindOAuthFailed", { provider: f[e.provider] }))
        );
      } else
        l.error(
          m(o, d("bindOAuthFailed", { provider: f[e.provider] }))
        );
    } finally {
      r.bindAuthLoading = !1;
    }
  }, W = async ({ session: t, connectedAccount: e }) => {
    r.unbindAuthLoading = !0;
    try {
      const o = t?.user?.sourceAppPid;
      await A.current.post("/unbind", {
        locale: p,
        connectedAccount: B(e, ["showProvider"]),
        sourceAppPid: o
      }), l.success(
        d("unbindOAuthSucceed", {
          provider: f[e.showProvider || e.provider]
        })
      ), _(e);
    } catch (o) {
      l.error(
        m(
          o,
          d("unbindOAuthFailed", {
            provider: f[e.showProvider || e.provider]
          })
        )
      );
    } finally {
      r.unbindAuthLoading = !1;
    }
  }, z = async (t = {}) => {
    try {
      const { data: e } = await A.current.get("/passports");
      e.length > 0 ? (c.open = !0, c.currentUser = t, c.passports = e || []) : l.error(d("noPassports"));
    } catch (e) {
      l.error(e.message || d("getPassportFailed"));
    }
  }, H = u((...t) => {
    c.reset(), I(...t);
  }), V = (t) => {
    r.baseUrl = t || "/";
  }, G = u(async ({ provider: t } = {}, { action: e = "login", ...o } = {}) => {
    const n = r.baseUrl;
    if (o?.sourceAppPid === window.blocklet?.appPid)
      r.baseUrl = window.blocklet?.appUrl || "/";
    else if (o?.sourceAppPid) {
      const a = await P(), s = C(a), g = k(a);
      s && g?.appPid && o?.sourceAppPid === g?.appPid && (r.baseUrl = g.appUrl);
    }
    const i = window?.blocklet?.componentId;
    try {
      const a = await L({ provider: t });
      if (r.baseUrl = n, await ce(100), a) {
        const s = {
          ...o,
          action: e,
          locale: p,
          code: a,
          provider: t,
          componentId: i
        };
        Q(s.inviter) && window.localStorage.getItem("inviter") && (s.inviter = window.localStorage.getItem("inviter"));
        const g = ["connect-to-did-space", "connect-to-did-domain"].includes(s.action) ? "login" : s.action, { data: $ } = await A.current.post("/login", { ...s, action: g }), y = ue($);
        return y.provider = t, y;
      }
      return r.baseUrl = n, null;
    } catch (a) {
      const s = m(a, d("loginOAuthFailed", { provider: f[t] }));
      throw r.baseUrl = n, new Error(s);
    }
  }), K = u(() => {
  });
  return /* @__PURE__ */ J(
    fe,
    {
      value: {
        locale: p,
        getOAuthConfigs: U,
        getOAuthConfigList: X,
        bindOAuth: q,
        unbindOAuth: W,
        loginOAuth: G,
        logoutOAuth: K,
        switchOAuthPassport: z,
        baseUrl: r.baseUrl,
        setBaseUrl: V,
        oauthState: b,
        unbindAuthLoading: r.unbindAuthLoading,
        bindAuthLoading: r.bindAuthLoading,
        t: d
      },
      children: [
        w,
        j,
        /* @__PURE__ */ E(
          le,
          {
            api: A.current,
            locale: p,
            switchState: c,
            onSwitchPassport: H,
            session: Y
          }
        )
      ]
    }
  );
}
function _e() {
  const w = Z(D);
  return B(w, ["locale", "getToken"]);
}
Ae.propTypes = {
  children: h.node.isRequired,
  locale: h.string,
  onBindOAuth: h.func,
  onUnbindOAuth: h.func,
  onSwitchPassport: h.func,
  session: h.object
};
export {
  Te as OAuthConsumer,
  D as OAuthContext,
  Ae as OAuthProvider,
  _e as useOAuth
};
