import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { observer } from 'mobx-react-lite';
import { useWixPatternsContainer } from '@wix/bex-core/react';
import {
  MultiSelect,
  Box,
  TextButton,
  listItemActionBuilder,
  DropdownLayoutOption,
  Divider,
  ListItemAction,
  Tag,
  Text,
} from '@wix/design-system';
import { Add as AddIcon } from '@wix/wix-ui-icons-common';
import { TagsWidgetBaseProps } from './TagsWidget';
import { runInAction } from 'mobx';
import {
  ADD_ITEM_OPTION_ID,
  MANAGE_TAGS_OPTION_ID,
  TAG_MAX_LENGTH,
  TagsFormState,
  TagsWidgetState,
} from '@wix/bex-core';
import { TagsModalState } from '../../state/TagsModalState';
import { useSelector } from '../../useSelector';

interface TagsWidgetContentProps
  extends Omit<
    TagsWidgetBaseProps,
    'subtitle' | 'dataHook' | 'status' | 'theme'
  > {
  state: TagsWidgetState;
}

const ReadonlyTagsWidgetContent = ({
  formState,
}: {
  formState: TagsFormState;
}) => {
  const { translate: t, initTask } = useWixPatternsContainer();
  useSelector(() => initTask.status);

  if (formState.displayedAssignedTags.length === 0) {
    return (
      <Text dataHook="tags-widget-readonly-empty-state">
        {t('cairo.tags.tagsField.readOnly.emptyState')}
      </Text>
    );
  }

  return (
    <Box gap="tiny">
      {formState.displayedAssignedTags.map((tag) => (
        <Tag
          key={tag.id}
          id={tag.id}
          dataHook="tags-widget-tag"
          removable={false}
        >
          {tag.label}
        </Tag>
      ))}
    </Box>
  );
};

const ManageTagsModal = React.lazy(() =>
  import(
    /* webpackChunkName: "ManageTagsModal" */ '../Tags/ManageTags/ManageTagsModal/ManageTagsModal'
  ).then((module) => ({ default: module.ManageTagsModal })),
);

const _TagsWidgetContent = ({
  state,
  onSubmit,
  entityTypeName,
  initialTags,
  entityId,
  readOnly,
}: TagsWidgetContentProps) => {
  const { translate: t } = useWixPatternsContainer();
  const [formState] = useState(() =>
    runInAction(
      () =>
        (state.tagsFormState ??= new TagsFormState({
          initialTags,
          tagsManagementState: state.tagsManagementState,
          origin: state.origin,
          entityTypeName,
        })),
    ),
  );
  const [tagsModalState] = useState(
    () =>
      new TagsModalState({
        tagsManagementState: state.tagsManagementState,
        entityTypeName,
      }),
  );

  useEffect(() => {
    const disposers = [formState.init({ entityId }), tagsModalState.init()];

    return () => {
      disposers.forEach((disposer) => disposer());
    };
  }, []);

  const tagsOptions = useMemo(() => {
    const options = formState.displayedTagOptions;

    const addTagOptionItems = formState.shouldShowCreateTagOption
      ? [
          listItemActionBuilder({
            id: ADD_ITEM_OPTION_ID,
            title: t('cairo.tags.tagsWidget.options.add.CTA', {
              tagName: formState.searchValue?.slice(0, TAG_MAX_LENGTH),
            }),
            prefixIcon: <AddIcon />,
          }),
        ]
      : [];

    return [...addTagOptionItems, ...options];
  }, [
    formState.displayedTagOptions,
    formState.searchValue,
    formState.shouldShowCreateTagOption,
    formState.displayedAssignedTags,
  ]);

  const handleSearchChange = useCallback((event) => {
    formState.handleSearchChange(event.target.value);
  }, []);

  const handleTagSelect = useCallback(
    async (option: DropdownLayoutOption) => {
      const convertedOption = {
        id: option.id as string,
        value: option.value as string,
      };
      formState.handleTagSelect(convertedOption, onSubmit);
    },
    [onSubmit],
  );

  const handleTagRemove = useCallback(
    (tagId) => {
      formState.unassignTag(tagId, onSubmit);
    },
    [onSubmit],
  );

  const handleOptionsShow = useCallback(() => {
    formState.handleOptionsShow();
  }, []);

  const handleManageTagsCtaClick = useCallback(() => {
    formState.handleManageTagsCtaClick();
    tagsModalState.openManageTagsModal({
      origin: formState.origin,
      tagSubOrigin: 'tagsWidget',
    });
  }, []);

  const handleMultiSelectFocus = useCallback(() => {
    formState.setIsMultiSelectOnFocus(true);
  }, []);

  const handleMultiSelectBlur = useCallback(() => {
    formState.setIsMultiSelectOnFocus(false);
  }, []);

  if (readOnly) {
    return <ReadonlyTagsWidgetContent formState={formState} />;
  }

  return (
    <>
      <MultiSelect
        value={formState.searchValue}
        onChange={handleSearchChange}
        options={tagsOptions}
        onFocus={handleMultiSelectFocus}
        onBlur={handleMultiSelectBlur}
        tags={formState.displayedAssignedTags}
        onOptionsShow={handleOptionsShow}
        markedOption={
          formState.shouldShowCreateTagOption ? ADD_ITEM_OPTION_ID : true
        }
        customSuffix={
          <Box>
            <TextButton
              size="small"
              prefixIcon={<AddIcon />}
              dataHook="assign-tags-cta"
            >
              {t('cairo.tags.tagsWidget.add.CTA')}
            </TextButton>
          </Box>
        }
        fixedFooter={
          formState.isInEmptyState ? undefined : (
            <div>
              {!!tagsOptions.length && <Divider />}
              <ListItemAction
                dataHook="manage-tags-cta"
                onClick={handleManageTagsCtaClick}
                id={MANAGE_TAGS_OPTION_ID}
                title={t('cairo.tags.tagsWidget.options.manage.CTA')}
              />
            </div>
          )
        }
        onSelect={handleTagSelect}
        onRemoveTag={handleTagRemove}
        placeholder={
          formState.isInEmptyState && formState.isMultiSelectOnFocus
            ? t('cairo.tags.tagsWidget.input.placeholder')
            : undefined
        }
        dataHook="tags-widget-multi-select"
      />
      <React.Suspense fallback={null}>
        <ManageTagsModal state={tagsModalState} />
      </React.Suspense>
    </>
  );
};

export const TagsWidgetContent = observer(_TagsWidgetContent);
