<%= importor.lifecycle? "import lifeCycle from './lowcode/lifecycle'" : "const lifeCycle = {}" %>
import { app, $app } from './app/weapps-api';
// 引入数据源管理器并进行初始化
import {
  setConfig,
  getAccessToken,
  EXTRA_API,
  createStateDataSourceVar,
  generateParamsParser,
} from './datasources/index';
import { redirectToLogin, findLoginPage, getAuthConfig, checkAnonymous } from './common/util';

// 防止报类型不匹配warning
const originWarn = console.warn;
const warningSkipRegexp = /(type-uncompatible)|(slot "[\w-]*?" is not found)/;
console.warn = (...args) => {
  // 只看第一条
  const shouldSkip = args.length > 0 && args[0][0] === '[' && args[0][1] === 'C' && warningSkipRegexp.test(args[0]);
  if (!shouldSkip) {
    originWarn(...args);
  }
};

// 设置数据源请求的 loading 及 toast 处理
setConfig({
  beforeDSRequest: (cfg) => {
    if (!cfg.options || !cfg.options.showLoading) return;
    app.showLoading();
  },
  beforeCallFunction: async (params) => {
    try {
      const loginPage = findLoginPage();

      let skip = false;
      switch (params?.data?.methodName) {
        case 'callWedaApi': {
          if (['GetMiniProgramUserTicket', 'DescribeRuntimeResourceStrategy'].includes(params?.data?.params.action)) {
            skip = true;
          }
          break;
        }
      }

      // 后续做过滤处理
      const endpointType = app?.__internal__?.getCloudSdkConfig('endpointType');
      if ((params?.data?.mode === 'c' && skip) || (endpointType !== 'tcb-api' && !loginPage)) {
        return params;
      }
      // await initTcb();
      const { accessToken } = await getAccessToken();
      if (accessToken) {
        params.data.accessToken = accessToken;
      }
    } catch (e) {
      if (app?.cloud?.currentUser?.userType === 'externalUser' && e?.error === 'unauthenticated') {
        app.showToast({
          title: '登录态失效',
          icon: 'error',
        });
      }
      // console.error('beforeCallFunction error', e);
    }
    return params;
  },
  afterDSRequest: (cfg, error, result) => {
    if (!cfg.options) return;
    if (cfg.options.showLoading) app.hideLoading();
    if (!cfg.options.showToast) return;
    const isSuccess = !error && result && !result.code;
    app.showToast({ icon: isSuccess ? 'success' : 'error' });
  },
  async afterCallFunction(params, error, res) {
    const oauthError =
      error?.message?.includes?.('PERMISSION_DENIED') ||
      error?.code === 'unauthenticated' ||
      error?.error === 'unauthenticated' ||
      error?.code === 'invalid_grant' ||
      error?.error === 'invalid_grant' ||
      error?.code === 'INVALID_ACCESS_TOKEN' ||
      (error?.code === 'OPERATION_FAIL' && /^\[INVALID_ACCESS_TOKEN\]/.test(error?.message || ''));

    if (
      params?.data?.params?.action != 'DescribeRuntimeResourceStrategy' &&
        (['InnerError.AuthFailure', 'InvalidAccessToken'].includes(res?.result?.code) ||
      oauthError)
    ) {
      const loginPage = findLoginPage();
      if (loginPage) {
        const authConfig = await getAuthConfig();
        if (authConfig.RejectStrategy === 'to_login') {
          if (['InnerError.AuthFailure'].includes(res?.result?.code)) {
            const isAnonymous = await checkAnonymous();
            if (!isAnonymous) return;
            // 匿名用户越权去登录
          }
          redirectToLogin();
        } else if (authConfig.RejectStrategy === 'show_warning') {
          if (oauthError) {
            const isAnonymous = await checkAnonymous();
            if (!isAnonymous) {
              redirectToLogin(generateLoginUrl);
              return;
            }
          }
          app.showToast({
            title: '接口无访问权限',
            icon: 'error',
          });
        }
      }
    }
  },
});

App({
  _query: {},
  globaldata: {
    _beforeCustomLaunchPromise: null,
  },
  async beforeCustomLaunch(query) {
    if (!this.globaldata?._beforeCustomLaunchPromise) {
      if (!this.globaldata) {
        this.globaldata = {};
      }
      this.globaldata._beforeCustomLaunchPromise = new Promise(async (resolve) => {
        try {
          EXTRA_API.setParams('$global', query || {});
          await createStateDataSourceVar('$global', generateParamsParser({ app, $page: {}, $w: app.__internal__?.$w }));
        } catch (e) {
          throw e;
        } finally {
          for (const queryId in app.dataset?.query || {}) {
            if (app.dataset.query[queryId]?._schema?.trigger === 'auto') {
              /**
               * query 初始化不阻塞生命周期
               */
              Promise.resolve()
                .then(async () => {
                  await app.dataset?.query?.[queryId]?.initPromise;
                  return app.dataset?.query?.[queryId]?.trigger?.();
                })
                .catch((e) => {
                  console.error(`query ${queryId} 初始化失败：`, e);
                });
            }
          }
          resolve();
        }
      });
    }
    return this.globaldata._beforeCustomLaunchPromise;
  },
  async onLaunch(options) {
    if (wx.onLazyLoadError) {
      wx.onLazyLoadError(({ type, subpackage, errMsg}) => {
        console.log('subpackage')
        if(type === 'subpackage' && subpackage?.find(item=>item === '<%= materialSubPackagePath %>')) {
          wx.showModal({
            title: '组件包加载失败',
            content: `加载组件包超时：${errMsg}，请退出重新进入。`,
            showCancel: false,
            success (res) {
              return
            }
          })

        }
      })
    }
    this.app = app;
    const onLaunch = lifeCycle.onLaunch || lifeCycle.onAppLaunch;
    let { query = {} } = options;
    this._query = query;

    await this.beforeCustomLaunch(query);
    onLaunch && onLaunch.call(this, options);
    // 初始私有全局数据
    this.$$global = {
      homePageId: '<%= appConfig.homePageId %>',
    };
  },
  async onShow(options) {
    await this.beforeCustomLaunch(this._query);
    const fn = lifeCycle.onShow || lifeCycle.onAppShow;
    fn && fn.call(this, options);
  },
  onHide() {
    const fn = lifeCycle.onHide || lifeCycle.onAppHide;
    fn && fn.call(this);
  },
  onError(msg) {
    const fn = lifeCycle.onError || lifeCycle.onAppError;
    fn && fn.call(this, msg);
  },
  onPageNotFound() {
    const fn = lifeCycle.onPageNotFound || lifeCycle.onAppPageNotFound;
    fn && fn.call(this);
  },
  onUnhandledRejection() {
    const fn = lifeCycle.onUnhandledRejection || lifeCycle.onAppUnhandledRejection;
    fn && fn.call(this);
  },
});
