import { createContext, use, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
import { RequestStorageAccessApiDialog } from '@arcblock/ux/lib/DIDConnect';
import { joinURL } from 'ufo';
import { getFederatedEnabled, getMaster } from '@arcblock/ux/lib/Util/federated';
import { useCreation, useMemoizedFn, useLocalStorageState, useInterval } from 'ahooks';
import { BLOCKLET_SERVICE_PATH_PREFIX } from '@arcblock/ux/lib/Util/constant';
import Cookie from 'js-cookie';

import { getBrowserLang } from '../utils';
import { CHECK_INTERVAL_TIME, LANG_COOKIE_NAME } from '../constant';

const FederatedContext = createContext({});
const { Provider, Consumer: FederatedConsumer } = FederatedContext;

function FederatedProvider({ children, locale: initialLocale = 'en' }) {
  const blocklet = window?.blocklet;
  const federatedEnabled = getFederatedEnabled(blocklet);
  const masterSite = getMaster(blocklet);
  const requestStorageAccessApiDialogRef = useRef(null);
  const [storageAccess, setStorageAccess] = useLocalStorageState('storage-access', {
    defaultValue: {
      appUrl: masterSite?.appUrl,
      iat: Date.now(),
      state: undefined,
    },
  });
  const [locale, setLocale] = useState(initialLocale);

  const checkCookieLocale = useMemoizedFn(() => {
    const latestLocale = Cookie.get(LANG_COOKIE_NAME) || getBrowserLang();
    if (latestLocale !== locale) {
      setLocale(latestLocale);
    }
  });

  const requestStorageAccess = useMemoizedFn(async () => {
    const { value: hasAccess, origin } = await requestStorageAccessApiDialogRef.current.requestStorageAccess();
    let state = storageAccess.state || 'prompt';
    if (origin === 'broswer') {
      if (storageAccess.state) state = hasAccess ? 'granted' : 'denied';
    }

    // NOTICE: 只有变化时才记录，确保 iat 值是相对可信的
    if (state !== storageAccess.state) {
      setStorageAccess({
        ...storageAccess,
        iat: Date.now(),
        state,
      });
    }
    return hasAccess;
  });

  const bridgeContent = useCreation(() => {
    if (masterSite?.appUrl && federatedEnabled) {
      return (
        <RequestStorageAccessApiDialog
          ref={requestStorageAccessApiDialogRef}
          locale={locale}
          src={joinURL(masterSite.appUrl, BLOCKLET_SERVICE_PATH_PREFIX, '/share/shared-bridge.html')}
          storageAccessState={storageAccess.state}
        />
      );
    }
    return null;
  }, [locale, masterSite?.appUrl, federatedEnabled, storageAccess.appUrl, storageAccess.iat, storageAccess.state]);

  useInterval(() => {
    checkCookieLocale();
  }, CHECK_INTERVAL_TIME);

  return (
    <Provider value={{ requestStorageAccess }}>
      {children}
      {bridgeContent}
    </Provider>
  );
}

FederatedProvider.propTypes = {
  children: PropTypes.node.isRequired,
  locale: PropTypes.string,
};

function useFederatedContext() {
  const context = use(FederatedContext);

  return omit(context, ['locale']);
}

export { FederatedContext, FederatedConsumer, FederatedProvider, useFederatedContext };
