import { useEffect, ReactElement, useRef, use } from 'react';
import Button from '@arcblock/ux/lib/Button';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { BLOCKLET_SERVICE_PATH_PREFIX } from '@arcblock/ux/lib/Util/constant';
import { useMemoizedFn, useReactive } from 'ahooks';
import { translate } from '@arcblock/ux/lib/Locale/util';
import { joinURL, withQuery } from 'ufo';
import { SessionContext } from '@arcblock/did-connect-react/lib/Session';
import Toast from '@arcblock/ux/lib/Toast';

import ResourceDialog from './resource-dialog';
import { translations } from '../libs/locales';
import type { SessionContext as TSessionContext } from '../../@types';

export default function AddComponent({
  componentDid,
  resourceType = undefined,
  resourceDid = undefined,
  grantedRoles = ['admin', 'owner'],
  autoClose = true,
  selectedMeta = undefined,
  storeUrl = undefined,
  onComplete,
  onClose,
  render = undefined,
}: {
  componentDid: string;
  resourceType?: string;
  resourceDid?: string;
  autoClose?: boolean;
  selectedMeta?: any;
  storeUrl?: string;
  grantedRoles?: string[];
  onComplete: () => void;
  onClose: () => void;
  render?: ({ onClick, loading }: { onClick: () => void; loading: boolean }) => ReactElement<any>;
}) {
  const { session } = use<TSessionContext>(SessionContext);
  const { locale } = useLocaleContext();
  const t = useMemoizedFn((key, data = {}) => {
    return translate(translations, key, locale, 'en', data);
  });
  const refIframe = useRef<{ selectBlocklet: (meta: any) => void }>(null);

  const currentState = useReactive({
    loading: false,
    showDialog: false,
  });
  const importUrl = withQuery(joinURL(BLOCKLET_SERVICE_PATH_PREFIX, 'embed/resources', componentDid, 'add'), {
    resourceDid,
    resourceType,
    mode: 'dialog',
    showFromUrl: 'false',
    showResourcesSwitch: 'false',
    enableRunBackground: 'false',
    showCategory: 'false',
  });

  const handleClose = useMemoizedFn(() => {
    currentState.showDialog = false;
    onClose?.();
  });
  const handleComplete = useMemoizedFn(() => {
    currentState.showDialog = false;
    onComplete?.();
  });
  const handleOpen = useMemoizedFn(() => {
    if (!session.user) {
      Toast.warning(t('needLogin'));
      return;
    }
    if (!grantedRoles.includes(session.user?.role as string)) {
      Toast.warning(t('noPermission'));
      return;
    }
    currentState.loading = true;
    currentState.showDialog = true;
  });
  const handleLoad = useMemoizedFn(() => {
    currentState.loading = false;
    if (refIframe.current) {
      refIframe.current?.selectBlocklet(selectedMeta);
    }
  });

  const handleIframeMessage = useMemoizedFn((event: MessageEvent) => {
    if (event?.data?.event === 'component.installed' && event.data.componentDid === componentDid) {
      if (autoClose || event.data.manual) {
        handleComplete();
      }
    }
  });

  useEffect(() => {
    if (currentState.showDialog) {
      window.addEventListener('message', handleIframeMessage);
    } else {
      window.removeEventListener('message', handleIframeMessage);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentState.showDialog]);

  return (
    <>
      {render ? (
        render({ onClick: handleOpen, loading: currentState.loading })
      ) : (
        <Button
          key="button"
          variant="outlined"
          color="secondary"
          type="button"
          className="submit"
          onClick={handleOpen}
          loading={currentState.loading}
          sx={{ mr: 1, ml: 1 }}>
          {t('importResource')}
        </Button>
      )}

      {currentState.showDialog && (
        <ResourceDialog
          ref={refIframe}
          src={importUrl}
          storeUrl={storeUrl}
          open
          componentDid={componentDid}
          loading={currentState.loading}
          onClose={handleClose}
          onComplete={handleComplete}
          onLoad={handleLoad}
        />
      )}
    </>
  );
}
