import {
  Box,
  Button,
  CustomModalLayout,
  Heading,
  ModalMobileLayout,
  Text,
} from '@wix/design-system';
import { getImportModalStepProps } from './getImportModalStepProps';
import React, { Suspense, lazy, useEffect, useMemo, useState } from 'react';
import { observer } from 'mobx-react-lite';
import { useCreateImport } from '@wix/bex-core';
import { detectFieldType } from '@wix/patterns-fields';
import { ImportButtonModalLayoutProps } from './ImportProps';
import { addEventListener } from '@wix/bex-core/util';
import { useIsMobile } from '../../hooks/useIsMobile';
import { CustomDrawerLayout } from '../CustomDrawerLayout';
import { ImportStepper } from './ImportStepper';
import { MessageActionModal } from '../ActionModal';
import { ModalWrapper } from '../CollectionModal';
import { PatternsFieldsProvider } from '../../providers';
import { useToolbarCollectionContext } from '../ToolbarCollectionContext';

function _ImportButtonModalLayout(props: ImportButtonModalLayoutProps) {
  const { config, importModalState, renderFieldEditor, ...rest } = props;

  const isMobile = useIsMobile();
  // The config is read live off the table's source, which is in context here (the
  // consumer builds `config` above the collection provider, so it can't be). Pass
  // the toolbar's fields source to ImportState, which builds the effective config.
  const toolbar = useToolbarCollectionContext();

  const createImport = useCreateImport({
    importInputs: config,
    fieldsSource: toolbar.collectionFieldsSource?.fieldsSource,
    // Media-aware detection (image/video/document/audio) lives in
    // patterns-fields; core defaults to primitive detection without it.
    // ImportState wires the schema-backed `mergeFields` from the source, so
    // created columns refresh with no wiring here (CAIRO-4400).
    detectColumnType: detectFieldType,
    importModalState,
  });

  const [state] = useState(() => createImport());

  // The create/edit-field editor follows the destination and is loaded on demand,
  // so neither the CMS nor the DataExtension editor is bundled until an import
  // that can create fields actually opens. A `renderFieldEditor` prop overrides.
  const isPlatformized = Boolean(config?.destination);
  const FieldEditor = useMemo(
    () =>
      lazy(() =>
        isPlatformized
          ? import('../DataExtension/DataExtensionImportFieldEditor').then(
              (m) => ({ default: m.DataExtensionImportFieldEditor }),
            )
          : import('./CmsImportFieldEditor').then((m) => ({
              default: m.CmsImportFieldEditor,
            })),
      ),
    [isPlatformized],
  );

  const {
    onRequestClose,
    children,
    removeContentPadding,
    ...customModalLayoutProps
  } = getImportModalStepProps({
    state,
    isMobile,
  });

  const wrappedChildren =
    state.currentStep !== 'progress' && state.currentStep !== 'summary' ? (
      <Box direction="vertical" gap="SP3" width="100%" height="100%">
        <ImportStepper
          state={state}
          removeContentPadding={!removeContentPadding}
        />
        {children}
      </Box>
    ) : (
      children
    );

  // The configuration step's "new field" helper reads field-type names from the
  // patterns-fields translations, which require this provider. Only mounted when
  // field creation is enabled (the only case a "new" mapping can exist), so the
  // fields container isn't initialized for plain imports.
  const content = state.canCreateNewField ? (
    <PatternsFieldsProvider>{wrappedChildren}</PatternsFieldsProvider>
  ) : (
    wrappedChildren
  );

  useEffect(() => {
    if (onRequestClose) {
      return addEventListener(
        importModalState.events,
        'requestClose',
        onRequestClose,
      );
    }

    return undefined;
  }, [onRequestClose]);

  useEffect(() => state.init(), []);

  const t = state.translate;

  const { modal: discardModal } = state.discardChangesModal;

  // The main layout + its discard-changes modal differ per device; everything
  // common (the field editor) is stacked alongside `child` in the single return.
  let child: React.ReactNode;

  if (isMobile) {
    child = (
      <>
        <CustomDrawerLayout
          dataHook="import-modal-layout"
          removeContentPadding={removeContentPadding}
          {...rest}
          {...customModalLayoutProps}
          children={content}
        />
        <ModalWrapper
          state={discardModal}
          onAfterClose={() => state.discardChangesModal.afterClose()}
        >
          <ModalMobileLayout
            dataHook="import-discard-changes-modal"
            title={
              <Heading size="small">
                {t('cairo.import.discardChanges.title')}
              </Heading>
            }
            content={
              <Text>{t('cairo.import.discardChanges.description')}</Text>
            }
            onCloseButtonClick={() => discardModal.close()}
            stickyFooter
            footer={
              <Box direction="vertical" gap="SP3">
                <Button
                  dataHook="import-discard-confirm"
                  fullWidth
                  skin="destructive"
                  onClick={() => discardModal.confirm()}
                >
                  {t('cairo.import.discardChanges.confirm')}
                </Button>
                <Button
                  dataHook="import-discard-cancel"
                  fullWidth
                  priority="secondary"
                  onClick={() => discardModal.decline()}
                >
                  {t('cairo.import.discardChanges.cancel')}
                </Button>
              </Box>
            }
          />
        </ModalWrapper>
      </>
    );
  } else {
    child = (
      <>
        <CustomModalLayout
          width="600px"
          maxHeight="80vh"
          dataHook="import-modal-layout"
          removeContentPadding={removeContentPadding}
          {...rest}
          {...customModalLayoutProps}
          children={content}
        />
        <MessageActionModal
          dataHook="import-discard-changes-modal"
          state={state.discardChangesModal}
          title={t('cairo.import.discardChanges.title')}
          content={t('cairo.import.discardChanges.description')}
          primaryButtonText={t('cairo.import.discardChanges.confirm')}
          secondaryButtonText={t('cairo.import.discardChanges.cancel')}
          theme="destructive"
        />
      </>
    );
  }

  return (
    <>
      {child}
      {state.canCreateNewField ? (
        renderFieldEditor ? (
          renderFieldEditor({ state })
        ) : (
          <Suspense fallback={null}>
            <FieldEditor state={state} />
          </Suspense>
        )
      ) : null}
    </>
  );
}

export const ImportButtonModalLayout = observer(_ImportButtonModalLayout);
