import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';

import { CONTEXT_OPEN_IN_VIDEO_EDIT_TAGS, TAG_SYSTEM_CATEGORY_IAB, TAG_SYSTEM_CATEGORY_TEXT } from '../constants';
import { CustomTagsPropType, SystemTagsPropType } from '../constants/propTypes';

import { clearAction, setStateAction } from '../redux/slices';

import TagCreate from './TagCreate';
import CustomTags from './Tags/CustomTags';
import SystemTags from './Tags/SystemTags';
import { Alert, Box, Dialog, DialogTitle, Grid, Stack } from '@/mui/components';

import styles from './TagEditor.module.scss';

function TagEditor({ excludeSystemTagsCategory = [], shouldExcludeAllCustomTags = false, isOpen = false, ...props }) {
  const dispatch = useDispatch();

  const disabledWhenUserCanSelectOnlyOneTag = props.shouldSelectOnlyOneTag
    ? !!props.systemTags.length || !!props.customTags.length
    : false;

  const getDialogTitle = () => {
    if (props.dialogTitle) {
      return props.dialogTitle;
    }

    return props.isEditable ? 'Tag Editor' : 'Tag Viewer';
  };

  const handleClose = () => {
    props.onClose();
    dispatch(clearAction());
  };

  // handlers for system tags
  const handleCreateSystemTag = ({ tag, category }) => {
    const categoryValue = category.value.toLowerCase();
    const formatter = (tagEntity) => ({
      id: categoryValue === TAG_SYSTEM_CATEGORY_TEXT.toLowerCase() ? tagEntity.value : tagEntity.id,
      type: categoryValue,
      text: tagEntity.value,
    });

    const tags = Array.isArray(tag) ? tag.map(formatter) : [formatter(tag)];

    let updatedSystemTags;

    if (category.value === TAG_SYSTEM_CATEGORY_IAB) {
      const withoutIab = props.systemTags.filter((t) => t.type !== TAG_SYSTEM_CATEGORY_IAB.toLowerCase());
      updatedSystemTags = [...withoutIab, ...tags];
    } else {
      updatedSystemTags = [...props.systemTags, ...tags];
    }

    props.onChangeSystemTag(updatedSystemTags);
  };

  const handleDeleteSystemTag = (tag) => {
    const tags = props.systemTags.filter((systemTag) => systemTag.id !== tag.id);

    props.onChangeSystemTag(tags);
  };

  // handlers for custom tags
  const handleCreateCustomTag = ({ tagValue, category }) => {
    const newCustomTag = {
      labelId: category.id,
      name: category.value,
      value: tagValue,
      color: category.color,
    };

    const tags = [].concat(props.customTags, [newCustomTag]);

    props.onChangeCustomTags(tags);
  };

  const handleDeleteCustomTag = (tag) => {
    const tags = props.customTags.filter(
      (customTag) =>
        !(customTag.labelId === tag.id && customTag.name === tag.category && customTag.value === tag.label),
    );

    props.onChangeCustomTags(tags);
  };

  const handleEditCustomTag = (newTag, oldTag) => {
    const tags = props.customTags.map((customTag) => {
      if (customTag.labelId === oldTag.id && customTag.name === oldTag.category && customTag.value === oldTag.label) {
        return {
          ...customTag,
          value: newTag.label,
        };
      }
      return customTag;
    });

    props.onChangeCustomTags(tags);
  };

  const handleEditCustomCategory = (updatedCategory) => {
    const tags = props.customTags.map((customTag) => {
      const mappedTag = { ...customTag };

      if (mappedTag.labelId === updatedCategory.id) {
        mappedTag.color = updatedCategory.color;
        mappedTag.name = updatedCategory.name;
      }

      return mappedTag;
    });

    props.onChangeCustomTags(tags);
  };

  useEffect(() => {
    dispatch(setStateAction({ openContext: props.openContext }));
  }, []);

  return (
    <>
      {isOpen && (
        <Dialog open={isOpen} maxWidth="x2l" onClose={handleClose}>
          <DialogTitle onClose={handleClose}>{getDialogTitle()}</DialogTitle>

          {props.customTopComponent && props.customTopComponent}

          {props.isEditable && (
            <TagCreate
              accountId={props.accountId}
              customTags={props.customTags}
              systemTags={props.systemTags}
              excludeSystemTagsCategory={excludeSystemTagsCategory}
              shouldExcludeAllCustomTags={shouldExcludeAllCustomTags}
              disabled={disabledWhenUserCanSelectOnlyOneTag}
              onCreateCustomTag={handleCreateCustomTag}
              onCreateSystemTag={handleCreateSystemTag}
            />
          )}

          {disabledWhenUserCanSelectOnlyOneTag && (
            <Stack className={styles.AlertRoot}>
              <Alert severity="info" variant="outlined" size="small" shape="rounded">
                You can have only one tag at a time
              </Alert>
            </Stack>
          )}

          <Box className={styles.TagsScroll}>
            <Grid container direction="column">
              <SystemTags
                tags={props.systemTags}
                excludeTagsCategory={excludeSystemTagsCategory}
                infoTooltip={props.infoTooltip}
                onDelete={props.isEditable ? handleDeleteSystemTag : null}
              />
              {!props.shouldExcludeAllCustomTags && (
                <CustomTags
                  tags={props.customTags}
                  accountId={props.accountId}
                  onDelete={props.isEditable ? handleDeleteCustomTag : null}
                  onEditTag={props.isEditable ? handleEditCustomTag : null}
                  onEditCategory={props.isEditable ? handleEditCustomCategory : null}
                />
              )}
            </Grid>
          </Box>
        </Dialog>
      )}
    </>
  );
}

TagEditor.defaultProps = {
  excludeSystemTagsCategory: [],
  isOpen: false,
  openContext: CONTEXT_OPEN_IN_VIDEO_EDIT_TAGS,
  customTopComponent: () => '',
  infoTooltip: null,
};

TagEditor.propTypes = {
  // from props
  isOpen: PropTypes.bool,
  isEditable: PropTypes.bool.isRequired,
  accountId: PropTypes.number.isRequired,
  systemTags: SystemTagsPropType.isRequired,
  customTags: CustomTagsPropType.isRequired,
  excludeSystemTagsCategory: PropTypes.arrayOf(PropTypes.string),
  shouldExcludeAllCustomTags: PropTypes.bool,
  dialogTitle: PropTypes.string,
  shouldSelectOnlyOneTag: PropTypes.bool,
  openContext: PropTypes.string,
  customTopComponent: PropTypes.node,
  infoTooltip: PropTypes.oneOf([
    null,
    PropTypes.shape({
      action: PropTypes.func,
      data: PropTypes.shape({}),
      tagKeywords: PropTypes.arrayOf(PropTypes.shape({})),
      context: PropTypes.string,
    }),
  ]),

  onChangeCustomTags: PropTypes.func.isRequired,
  onChangeSystemTag: PropTypes.func.isRequired,
  onClose: PropTypes.func.isRequired,
};

export default TagEditor;
