import sdk from '@tcwd/weapps-sdk/lib/app-h5-sdk';

import {
  createWebApp,
  _ACTIONS_KEY as ACTIONS_KEY,
  _ROUTER_KEY as ROUTER_KEY,
  _WEDA_CLOUD_SDK as WEDA_CLOUD_SDK,
} from '@cloudbase/weda-client';
import { runtime } from '../utils/adapter/index';
import { getEnumOptions } from '../utils/initGlobalVar';

const { EXTRA_API, createDataset } = WEDA_CLOUD_SDK;

interface IBaseState {
  state: {
    [key: string]: any;
  };
  computed: {
    [key: string]: any;
  };
  dataset?: {
    state?: {};
  };
}

enum EPLATFORM {
  WEB = 'WEB',
  /**
   * 拼写错误
   * 兼容性无法修改
   */
  MINIPROGRAM = 'MINIPROGRAME',
}

export const subPackageName = '';
export let app = createGlboalApi();
export function registerApp(_app = createGlboalApi()) {
  _injectApp2Runtime(_app, true);
  app = _app;
}

mountAPIs(sdk);
export interface IAppAPI extends IBaseState {
  id: string;
  platform: EPLATFORM;
  __internal__?: {
    getConfig: Function;
  };
  app?: IAppAPI;
  $app?: IAppAPI;
  mainApp?: IAppAPI;
  common: {};
  enumOptions?: {};
  domain: string;
  cloud;
  /**
   * @deprecated
   */
  dataSources;
  utils: {
    formatDate: Function;
    formatEnum: Function;
    get: Function;
    set: Function;
    getCurrentPage: Function;
  };
  /**
   * 内置方法
   */
  _setStateVal: ({ varPath, val }) => void;
  setState: (state) => void;
  /**
   * 微信继承方法
   */
  showLoading?: (param?) => void;
  hideLoading?: () => void;
  showToast?: (param) => void;
  redirectTo?: (param) => void;
}

function createGlboalApi(
  initData: {
    id?: string;
    domain?: string;
    appConfig?: {
      id?: string;
      envId?: string;
      envVersion?: 'preview' | 'production';
      staticResourceDomain?: string;
      pages: { id: string }[];
    };
  } = {}
): IAppAPI {
  const webApp = createWebApp(initData);
  const globalAPI: IAppAPI = new Proxy(
    {
      id: initData.id || '',
      domain: initData.domain || '',
      state: {},
      computed: {},
      dataset: {},
      common: {},
      enumOptions: {},
      // i18n,
      ...webApp,
      utils: {
        ...webApp.utils,
        formatEnum: (path, optionname, app) => {
          let isSingle = Array.isArray(path);
          // 这个app是后来添加进去的
          let options = app?.enumOptions;
          let parseOptions = options[optionname]
            ? options[optionname]
            : getEnumOptions(optionname);
          if (parseOptions === '') {
            return !isSingle ? path : path.join(',');
          }
          let multiTmp = [];
          let value = !isSingle
            ? JSON.parse(parseOptions)?.find((item) => item.key === path)?.value
            : JSON.parse(parseOptions)
                ?.filter((item) =>
                  path.some((pathValue) => item.key === pathValue)
                )
                .map((item) => multiTmp.push(item.value));
          return !isSingle ? value : multiTmp.join(',');
        },
      },
      /**
       * setState
       */
      setState: (userSetState) => {
        Object.keys(userSetState).forEach((keyPath) => {
          globalAPI.utils.set(
            globalAPI.dataset.state,
            keyPath,
            userSetState[keyPath]
          );
        });
      },
    },
    {
      get: (obj, prop) => {
        if (prop === 'app' || prop === '$app') {
          return app;
        } else {
          return obj[prop];
        }
      },
      // set: (obj, prop, value) => {
      //   if (prop === 'app' || prop === '$app') {
      //     console.warn('$app 对象中 app/$app 为只读');
      //     return false;
      //   } else {
      //     // 修改 obj
      //     return true;
      //   }
      // },
    }
  );
  _injectApp2Runtime(globalAPI);

  return globalAPI;
}

function _injectApp2Runtime(globalAPI, hard = false) {
  // 给全局挂上 mainApp/subApp
  // The global api exposed to lowcode
  if (subPackageName) {
    globalAPI.mainApp = runtime[`$app`];
    (runtime as any)[`$$subapp_${subPackageName}`] = globalAPI;
  } else {
    // 预览区调试栏可调试
    // 暴露给复合组件，代码组件来引用
    runtime['app'] = hard ? globalAPI : runtime['app'] || globalAPI;
    runtime[`$app`] = runtime['app'];
  }
}

export function removeGlboalApi() {
  if (subPackageName) {
    (runtime as any)[`$$subapp_${subPackageName}`] = undefined;
  } else {
    runtime['app'] = undefined;
    runtime[`$app`] = undefined;
  }
}

export interface IPageAPI extends IBaseState {
  $page?: IPageAPI;
  handler: {
    [key: string]: any;
  };
  props: {
    [key: string]: any;
  };
  widgets: {
    [key: string]: any;
  };
  setState: (state) => void;
  _dataBinds: {
    [key: string]: any;
  };
}

export function createPageApi(): IPageAPI {
  const $page: IPageAPI = new Proxy(
    {
      state: {},
      computed: {},
      handler: {},
      props: {},
      widgets: {},
      dataset: {},
      setState: (userSetState) => {
        Object.keys(userSetState).forEach((keyPath) => {
          app.utils.set($page.dataset?.state, keyPath, userSetState[keyPath]);
        });
      },
      _dataBinds: {},
    },
    {
      get(obj, prop) {
        return prop === '$page' ? obj : obj[prop];
      },
    }
  );
  return $page;
}

// 分app 和 wx 挂载app
function mountAPIs(sdks) {
  Object.keys(sdks).forEach((item) => {
    let action = sdks[item];
    if (!(item in ACTIONS_KEY) && !(item in ROUTER_KEY)) {
      app[item] = action;
    }
  });
  return app;
}
