import React, { useMemo, useRef } from 'react';
import { observer } from 'mobx-react-lite';
import {
  Box,
  DropdownPropsControlled as DropdownProps,
  Input,
  Loader,
} from '@wix/design-system';
import { CollectionViewsState } from '../../state';
import { FiltersMap } from '@wix/bex-core';
import { ViewsDropdownModals } from './ViewsDropdownModals';
import { View } from '../../model';
import { classes, st } from './ViewsDropdown.st.css.js';
import {
  ManageViewPopover,
  ManageViewPopoverHandle,
} from './ManageViewPopover';
import {
  buildCategoryOption,
  buildViewOption,
  getCategoryName,
  getViewName,
} from './viewsDropdownRenderHelpers';
import { AutoCompleteReadonly } from './AutoCompleteReadonly';
import { SaveToNewViewFooter } from './SaveToNewViewFooter';
import { ViewsDropdownPrefix } from './ViewsDropdownPrefix';
import { useWixPatternsContainer } from '@wix/bex-core/react';
import { useBmHarmonyTheme } from '../../hooks/useBmHarmonyTheme';

export const VIEWS_REDESIGN_EXPERIMENT = 'specs.cairo.ViewsRedesign';

export type ViewsDropdownProps<T, F extends FiltersMap> = {
  state: CollectionViewsState<T, F>;
  onSelect?: (view: View<F>) => void;
  dataHook: string;
  showTotal?: boolean;
} & Omit<DropdownProps, 'onSelect'>;

function _ViewsDropdown<T, F extends FiltersMap>({
  onSelect,
  dataHook,
  state,
  showTotal = true,
  dropdownWidth = '200px',
  ...dropdownProps
}: ViewsDropdownProps<T, F>) {
  const container = useWixPatternsContainer();
  const isRedesign = container.internalExperiments?.enabled(
    VIEWS_REDESIGN_EXPERIMENT,
  );
  const isBmHarmonyTheme = useBmHarmonyTheme();
  const { views: viewsState } = state;
  const { currentView, collection, localSearchState } = viewsState;
  const { filteredCategoriesWithViews } = localSearchState;
  const { translate: t } = collection;
  const showLoader =
    collection.result.status.isIdle || collection.result.status.isLoading;

  const manageViewRef = useRef<ManageViewPopoverHandle>(null);
  const viewsOptions = useMemo(() => {
    const { viewsWithoutCategory, categories } = filteredCategoriesWithViews;

    const buildOption = (view: (typeof viewsWithoutCategory)[number]) => {
      const isSelected = currentView?.id === view.id;
      const option = buildViewOption({
        view,
        viewsState,
        suffix:
          isRedesign && isSelected ? (
            <ManageViewPopover
              ref={manageViewRef}
              origin="MainToolbar"
              state={state}
              redesign
            />
          ) : undefined,
      });

      return option;
    };

    return [
      ...viewsWithoutCategory.map(buildOption),
      ...categories.flatMap((category) => [
        ...(getCategoryName({ category, viewsState })
          ? [buildCategoryOption({ category, viewsState })]
          : []),
        ...category.views.map(buildOption),
      ]),
    ];
  }, [
    filteredCategoriesWithViews,
    container.initTask.status,
    currentView?.id,
    isRedesign,
  ]);

  const { options, fixedFooter } = showLoader
    ? {
        options: [],
        fixedFooter: (
          <Box
            dataHook="initial-loader"
            width="100%"
            align="center"
            verticalAlign="middle"
            padding="SP2"
          >
            <Loader size="small" />
          </Box>
        ),
      }
    : {
        options: viewsOptions,
        fixedFooter: isRedesign ? (
          <SaveToNewViewFooter state={state} />
        ) : undefined,
      };

  const {
    table: { collection: mainCollection },
  } = state;

  const shouldShowTotal =
    showTotal &&
    (mainCollection.totalStatus === 'success' ||
      mainCollection.showRefreshLoader);

  return (
    <Box dataHook={dataHook}>
      <Box width={dropdownWidth} direction="vertical">
        <AutoCompleteReadonly
          emptyStateMessage={
            !showLoader && t('cairo.viewsDropdown.nothingMatches.text')
          }
          state={state.views.autoCompleteReadonlyState}
          value={localSearchState.inputValue}
          onChange={(e) =>
            localSearchState.setInputValueAndScheduleSearch(e.target.value)
          }
          clearInput={() => localSearchState.clearSearch()}
          dropdownWidth={isRedesign ? '264px' : dropdownWidth}
          popoverProps={{ placement: 'bottom-start' }}
          {...dropdownProps}
          onDrillIn={
            isRedesign
              ? (option) => {
                  if (option.id === currentView?.id) {
                    manageViewRef.current?.focusTrigger();
                  }
                }
              : undefined
          }
          onInputClicked={(e) => {
            state.viewsStateBIReporter.clickOnViewDropdownBI();
            dropdownProps?.onInputClicked?.(e);
          }}
          fixedFooter={fixedFooter}
          border={isBmHarmonyTheme ? 'standard' : 'round'}
          selectedId={currentView?.id}
          selectedLabel={
            currentView
              ? getViewName({ view: currentView, viewsState })
              : undefined
          }
          textOverflow="ellipsis"
          prefix={
            <div
              data-hook="views-dropdown-prefix"
              onClick={() => viewsState.autoCompleteReadonlyState.focusInput()}
              style={{ cursor: 'pointer', display: 'inline-flex' }}
            >
              <ViewsDropdownPrefix state={state} />
            </div>
          }
          suffix={
            shouldShowTotal ? (
              <div
                data-hook="views-dropdown-suffix"
                onClick={() =>
                  viewsState.autoCompleteReadonlyState.focusInput()
                }
                style={{ cursor: 'pointer', display: 'inline-flex' }}
              >
                <Box className="total-count">
                  <Input.Affix>
                    ({state.table.collection.result.total})
                  </Input.Affix>
                </Box>
              </div>
            ) : undefined
          }
          className={st(classes.root)}
          dataHook="collection-views-dropdown"
          onSelect={(option) => {
            viewsState.events.emit('beforeSelectView');
            const id = option.id.toString();
            const view = viewsState.getView(id);
            if (view) {
              onSelect?.(view);
              viewsState.selectView({ id });
              viewsState.events.emit('afterSelectView', { view });
            }
            localSearchState.clearSearch();
          }}
          options={options}
          placeholder={t('cairo.viewDropdown.unsavedView.status')}
        />
      </Box>

      {!isRedesign && (
        <Box verticalAlign="middle" paddingLeft="SP2">
          <ManageViewPopover origin="MainToolbar" state={state} />
        </Box>
      )}

      <ViewsDropdownModals state={state} />
    </Box>
  );
}

export const ViewsDropdown = observer(_ViewsDropdown);
