import { useCreation, useMemoizedFn, useReactive, useRequest } from 'ahooks';
import { joinURL } from 'ufo';
import pick from 'lodash/pick';
import unionBy from 'lodash/unionBy';
import sortBy from 'lodash/sortBy';
import Toast from '@arcblock/ux/lib/Toast';

import { BLOCKLET_SERVICE_PATH_PREFIX } from '../../constant';
import { createAxios, logger } from '../../utils';

const prefix = joinURL(BLOCKLET_SERVICE_PATH_PREFIX, '/api/user-session');

export default function useQuickConnect({
  appPid,
  sourceAppPid,
  loginAppPid,
  autoFetch = true,
  baseUrl = '/',
  fetchAll = false,
} = {}) {
  const api = useCreation(() => {
    return createAxios(
      {
        baseURL: joinURL(baseUrl, prefix),
      },
      { lazy: true, lazyTime: 500 }
    );
  }, [baseUrl]);

  const getUserSessions = useMemoizedFn(async () => {
    if (!window.blocklet) {
      return [];
    }

    let userSessions = [];
    try {
      ({ data: userSessions = [] } = await api.get(''));
    } catch (err) {
      logger.error('Failed to get user-sessions', err);
    }
    // NOTICE: 已经包含了 federated master userSessions
    const result = userSessions
      .filter((x) => {
        if (!fetchAll) {
          return !x.appUrl;
        }
        return true;
      })
      .map((x) => ({
        appUrl: baseUrl,
        ...x,
      }));
    return result;
  });
  const currentState = useReactive({
    loaded: false,
    loadingId: null,
  });
  const userSessionsState = useRequest(getUserSessions, {
    manual: !autoFetch,
    onFinally() {
      currentState.loaded = true;
    },
    refreshDeps: [baseUrl],
  });

  const loginUserSession = async (userSession) => {
    const params = pick(userSession, ['userDid', 'visitorId', 'passportId', 'id']);
    try {
      currentState.loadingId = userSession.id;
      const { data } = await api.post(
        'login',
        { ...params, appPid: loginAppPid },
        {
          baseURL: joinURL(userSession.appUrl || '/', prefix),
        }
      );
      return data;
    } catch (err) {
      const errorMsg = err.response ? err.response?.data?.error || err.response?.data : err.message;
      Toast.error(errorMsg);
      logger.error('Quick login error', err);
      throw err;
    } finally {
      currentState.loadingId = null;
    }
  };

  const onlineUserSessions = useCreation(() => {
    if (!userSessionsState.data) return [];
    return userSessionsState.data.filter((x) => x.status !== 'expired');
  }, [userSessionsState.data]);

  const uniqueUserSessions = useCreation(() => {
    const now = new Date().getTime();
    const sortedUserSessions = sortBy(onlineUserSessions, (x) => now - new Date(x.updatedAt).getTime());
    return unionBy(sortedUserSessions, (x) =>
      [
        x.userDid,
        // 暂不以用户角色来做去重的因子
        // x.user.role
      ].join('_')
    );
  }, [onlineUserSessions, sourceAppPid, appPid]);

  const quickLoginEnabled = useCreation(() => {
    return Boolean(uniqueUserSessions && uniqueUserSessions.length > 0);
  }, [uniqueUserSessions]);

  return {
    loadingId: currentState.loadingId,
    userSessions: uniqueUserSessions,
    quickLoginEnabled,
    loginUserSession,
    loading: userSessionsState.loading,
    loaded: userSessionsState.loaded,
    refresh: userSessionsState.refreshAsync,
  };
}
