/* eslint-disable @typescript-eslint/no-empty-function */
/**
 * 生命周期处理函数
 */
import * as React from 'react';
import { throttle } from 'lodash-es';
import * as querystring from 'query-string';
import { IAppAPI, IPageAPI } from '../app/global-api';
import { runtime } from './adapter';
import { ENABLE_WECOM, getNetworkType } from './common';
import { signInWidthProviderCode } from './sso';
// import { useHistory, useLocation } from 'react-router';
import { parseProviderTokenError } from './sso/error-handler';
import { auth } from '@cloudbase/weda-client';

const noops = () => {};

const APPLIFECYCLE = {
  onAppShow: noops,
  onAppHide: noops,
  onAppError: noops,
  onAppUnhandledRejection: noops,
  onAppLaunch: noops,
  beforeCustomLaunch: noops,
};

// 小程序 端使用lifeCycle
let alreadyInitAppLifeCycle = false;
let _HANDLER_MAP = {};
export function initAppLifeCycle(app, appLifeCycle, force = false) {
  appLifeCycle = { ...APPLIFECYCLE, ...appLifeCycle };

  async function scheduleAppLifecycle() {
    const options = app.getLaunchOptionsSync();
    const { query = {} } = options;
    const { state, code } = query;

    if (ENABLE_WECOM && query.code && query.state) {
      try {
        await signInWidthProviderCode(state, code);
        await auth.getUserInfo(true);
      } catch (e) {
        console.error(`企微登录失败: ${JSON.stringify({ state, code })}`, e);
        app['showModal']({
          content: `${parseProviderTokenError(e)} [${JSON.stringify({
            reqId: e?.request_id || '',
            state,
            code,
          })}]`,
          success(res) {
            if (res.confirm) {
              runtime.location.reload();
            }
          },
        });
        throw e;
      } finally {
        delete query.state;
        delete query.code;
        delete query.appid;
        const url = new URL(runtime.location.href);
        url?.searchParams?.delete?.('code');
        url?.searchParams?.delete?.('state');
        url?.searchParams?.delete?.('appid');
        runtime.history.replaceState({ _isLoginRoot: true }, '', url.toString());
        // const popHandler = function (e) {
        //   const { _isLoginRoot } = e.state;
        //   console.log('pop state', e.state);
        //   if (_isLoginRoot) {
        //     runtime?.['WeixinJSBridge']?.call?.('closeWindow');
        //   }
        // };
        // runtime.addEventListener('popstate', (e) => {
        //   popHandler(e);
        //   runtime.removeEventListener('popstate', popHandler);
        // });
      }
    }

    await appLifeCycle?.beforeCustomLaunch(query);
    appLifeCycle?.onAppLaunch(options);
    appLifeCycle?.onAppShow(options);
  }

  if (force) {
    removeAppLifeCycle();
  }
  // 应用级别事件监听
  if (!alreadyInitAppLifeCycle) {
    scheduleAppLifecycle();

    // 预留等客户端来触发
    _HANDLER_MAP = {
      appShow: (...args) => appLifeCycle.onAppShow(...args),
      appHide: (...args) => appLifeCycle.onAppHide(...args),
      error: (...args) => appLifeCycle.onAppError(...args),
      unhandledrejection: (event) => appLifeCycle.onAppUnhandledRejection(event?.reason),
    };
    for (const event in _HANDLER_MAP) {
      runtime.addEventListener(event, _HANDLER_MAP[event]);
    }
    alreadyInitAppLifeCycle = true;
  }
}

export function removeAppLifeCycle() {
  for (const event in _HANDLER_MAP) {
    runtime.removeEventListener(event, _HANDLER_MAP[event]);
  }
  _HANDLER_MAP = {};
  alreadyInitAppLifeCycle = false;
}

let isReachBottom = false;

type TPageLifecycleRes = Promise<void> | void;
interface IPageLifecycle {
  beforePageCustomLaunch?: (query) => Promise<void>;
  onPageLoad?: (query) => TPageLifecycleRes;
  onPageShow?: () => TPageLifecycleRes;
  onPageReady?: () => TPageLifecycleRes;
  onPageHide?: () => TPageLifecycleRes;
  onPageUnload?: () => TPageLifecycleRes;
  onReachBottom?: () => TPageLifecycleRes;
  onShareAppMessage?: () => TPageLifecycleRes;
  onPageScroll?: () => TPageLifecycleRes;
  onResize?: () => TPageLifecycleRes;
}
export function generatePageLifecycleHandlers(
  {
    beforePageCustomLaunch = async function (query) {},
    onPageLoad = function (query) {},
    onPageShow = function () {},
    onPageReady = function () {},
    onPageHide = function () {},
    onPageUnload = function () {},
    onReachBottom = function () {},
    onShareAppMessage = function () {},
    onPageScroll = function () {},
    onResize = function () {},
  }: IPageLifecycle,
  events,
) {
  function ensureDelegater(fn, eventsKey = '') {
    return function (...args) {
      typeof fn === 'function' && fn.call(this, ...args);
      if (eventsKey) {
        events[eventsKey]();
      }
    };
  }

  return {
    beforePageCustomLaunch,
    onPageLoad(query) {
      let callHandlerResult = typeof onPageLoad === 'function' ? onPageLoad.call(this, query) : () => {};
      events.load({ query });
      return callHandlerResult;
    },
    onPageShow: ensureDelegater(onPageShow, 'show'),
    onPageReady: ensureDelegater(onPageReady, 'ready'),
    onPageHide: ensureDelegater(onPageHide, 'hide'),
    onPageUnload: ensureDelegater(onPageUnload, 'unload'),
    onReachBottom: ensureDelegater(onReachBottom),
    onShareAppMessage: ensureDelegater(onShareAppMessage),
    onPageScroll: ensureDelegater(onPageScroll),
    onResize: ensureDelegater(onResize),
  };
}

// web 端使用lifeCycle
export function usePageLifeCycle(
  {
    beforePageCustomLaunch = async function (query) {},
    onPageLoad = function (query) {},
    onPageShow = function () {},
    onPageReady = function () {},
    onPageHide = function () {},
    onPageUnload = function () {},
    onReachBottom = function () {},
    onShareAppMessage = function () {},
    onPageScroll = function () {},
    onResize = function () {},
  }: IPageLifecycle,
  context: { app: IAppAPI; page: IPageAPI; options },
  deps = [],
) {
  let reachBottomDistance = 50;
  try {
    const config = context.app.__internal__.getConfig().pages.find((page) => page.id === context.page.id);
    reachBottomDistance = config.reachBottomDistance;
    if (typeof reachBottomDistance !== 'number') {
      reachBottomDistance = 50;
    }
  } catch (e) {}

  React.useEffect(() => {
    async function schedulePageLifecycle() {
      try {
        const query = getCurrentPageQuery();
        await beforePageCustomLaunch?.(query);

        onPageLoad?.call?.(context.page, query);
        onPageShow?.call?.(context.page);

        onPageReady?.call?.(context.page);
      } catch (e) {
        if (!context.options?.looseError) {
          throw e;
        } else {
          console.error('Catched error:', e);
        }
      }
    }

    schedulePageLifecycle();

    return () => {
      try {
        onPageHide?.call?.(context.page, {});
        onPageUnload?.call?.(context.page, {});
      } catch (e) {
        if (!context.options?.looseError) {
          throw e;
        } else {
          console.error('Catched error:', e);
        }
      }
    };
  }, deps);

  React.useEffect(() => {
    runtime.onscroll = throttle(() => {
      // 变量scrollTop是滚动条滚动时，滚动条上端距离顶部的距离
      let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

      // 变量windowHeight是可视区的高度
      let windowHeight = document.documentElement.clientHeight || document.body.clientHeight;

      // 变量scrollHeight是滚动条的总高度（当前可滚动的页面的总高度）
      let scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
      onPageScroll.call(context.page, {
        scrollTop: runtime.pageYOffset,
      });

      // console.log(scrollTop, windowHeight, scrollTop + windowHeight, scrollHeight, isReachBottom)
      // 滚动条到底部
      if (scrollTop + windowHeight >= scrollHeight - reachBottomDistance) {
        // 要进行的操作
        if (!isReachBottom) {
          isReachBottom = true;
          onReachBottom.call(context.page);
        }
      } else {
        isReachBottom = false;
      }
    }, 300);
    // todo
    if (typeof onShareAppMessage === 'function') {
      runtime['onShareAppMessage'] = onShareAppMessage.bind(context.page);
    }

    runtime.onresize = throttle(() => {
      onResize.call(context.page, {
        size: {
          windowWidth: runtime.innerWidth,
          windowHeight: runtime.innerHeight,
        },
      });

      const device = context.page.__internal__.$w?.device;
      if (device) {
        device.viewport = {
          width: runtime.innerWidth,
          height: runtime.innerHeight,
        };
      }
    }, 100);

    const navigator: any = runtime?.navigator || {};
    const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
    const isMobile = context.app?.__internal__?.isMobile;

    const connectionListener = () => {
      const device = context.page.__internal__.$w?.device;
      if (isMobile?.()) {
        device.networkType = getNetworkType(runtime);
      } else {
        device.networkType = '';
      }
    };
    connection?.addEventListener('change', connectionListener);
    return () => {
      runtime.onscroll = null;
      runtime.onresize = null;
      connection?.removeEventListener('change', connectionListener);
    };
  }, []);
}

function getCurrentPageQuery() {
  let queryObj = querystring.parse((location.search || '').split('?')[1] || '') || {};
  let hashQueryObj = querystring.parse((location.hash || '').split('?')[1] || '') || {};
  let query = { ...hashQueryObj, ...queryObj };
  // query string parse decode succeess
  // Object.keys(query).forEach((key) => {
  //   query[key] = decodeURIComponent(query[key] as string);
  // });
  return query;
}

export function initWebConfig(app, appConfig) {
  // miniprogram.config 配置截取
  app.setConfig(appConfig);
}
