import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'clsx';
import { InfoOutlined } from '@mui/icons-material';

import { iabClassificationCategoriesCollection, numberInRange } from '../../helpers';
import { dictionaryBlockInfoComputedSelector } from '../../redux/selectors';
import {
  saveConfigurationDataOnServerAction,
  updateConfigurationByPropAction,
  uploadConfigFileAction,
} from '../../redux/slices';

import ButtonsFileLoader from './buttonsFileLoader';
import MultiButtonsFileLoader from './multiButtonsFileLoader';
import {
  Autocomplete,
  Button,
  CircularProgress,
  Paper,
  Stack,
  Switch,
  TextField,
  Tooltip,
  Typography,
} from '@/mui/components';

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

const brandSafetyCategoriesCollection = [
  {
    name: 'BRAND_SAFETY',
    value: 'BRAND_SAFETY',
  },
];

function Dictionary() {
  const dispatch = useDispatch();
  const dictionaryBlockInfo = useSelector(dictionaryBlockInfoComputedSelector);

  const onBlurInput = ({ min, max, isFloat, fieldName, value }) => {
    const resultValue = numberInRange({
      min,
      max,
      isFloat,
      value,
    });

    dispatch(
      updateConfigurationByPropAction({
        [fieldName]: Number.isNaN(resultValue) ? min : resultValue,
      }),
    );
  };

  const onChangeInput = ({ min, max, isFloat, fieldName, value }) => {
    const resultValue = numberInRange({
      min,
      max,
      isFloat,
      value,
    });

    dispatch(
      updateConfigurationByPropAction({
        [fieldName]: Number.isNaN(resultValue) ? null : resultValue,
      }),
    );
  };
  const onChangeCheckbox = (fieldName, value) => {
    dispatch(
      updateConfigurationByPropAction({
        [fieldName]: value,
      }),
    );
  };

  const fileLoaders = [
    {
      title: 'Keywords Blacklist',
      description: 'Source keywords to remove from analysis',
      dictionary: dictionaryBlockInfo.dictionaryBlacklistFile,
      dictionaryName: 'dictionaryBlacklistFile',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Keywords Map',
      description: 'Mapping diverse keywords into standardized dictionary',
      dictionary: dictionaryBlockInfo.dictionaryMapFile,
      dictionaryName: 'dictionaryMapFile',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Keywords Categorization',

      description:
        'List of keywords from one category (like General) that should be processed as other category (like Brand Safety)',
      dictionary: dictionaryBlockInfo.dictionaryCategorizationFile,
      dictionaryName: 'dictionaryCategorizationFile',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Final Filter',
      description: 'Thresholds for final tag filtering (per category)',
      dictionary: dictionaryBlockInfo.dictionaryFilterFile,
      dictionaryName: 'dictionaryFilterFile',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Brand Safety Tags',
      description: 'Mapping of unsafe keywords into BrandSafety tags/groups',
      dictionary: dictionaryBlockInfo.dictionaryBrandSafetyFile,
      dictionaryName: 'dictionaryBrandSafetyFile',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Keywords to IAB Map',
      description: 'Mapping keywords into their corresponding IAB categories',
      dictionary: dictionaryBlockInfo.classificationIabMapFile,
      dictionaryName: 'classificationIabMapFile',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Iab merging weights',
      description: 'Iab merging (correction) weights',
      dictionary: dictionaryBlockInfo.classificationIabWeightsFile,
      dictionaryName: 'classificationIabWeightsFile',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Celebrities to IAB Map',
      description: 'Mapping celebrities into their corresponding IAB categories',
      dictionary: dictionaryBlockInfo.classificationIabCelebritiesMapFile,
      dictionaryName: 'classificationIabCelebritiesMapFile',
      allowedExtensions: ['.csv'],
    },
  ];

  const multiFileLoaders = [
    {
      title: 'Text to Brand Safety Map',
      description: 'Mapping text into their corresponding BrandSafety tags',
      dictionary: dictionaryBlockInfo.dictionaryBrandSafetyText,
      dictionaryName: 'dictionaryBrandSafetyText',
      allowedExtensions: ['.csv'],
    },
    {
      title: 'Speech to Brand Safety Map',
      description: 'Mapping speech into their corresponding BrandSafety tags',
      dictionary: dictionaryBlockInfo.dictionaryBrandSafetySpeech,
      dictionaryName: 'dictionaryBrandSafetySpeech',
      allowedExtensions: ['.csv'],
    },
  ];

  const inputsFormCollection = [
    {
      title: 'IAB classification count',
      value: dictionaryBlockInfo.classificationIabCount,
      propStateName: 'classificationIabCount',
      min: 0,
      step: 1,
      max: 100,
      isFloat: false,
    },
    {
      title: 'IAB classification lower bound',
      value: dictionaryBlockInfo.classificationIabLowerbound,
      propStateName: 'classificationIabLowerbound',
      min: 0,
      step: 0.01,
      max: 1,
      isFloat: true,
    },
    {
      title: 'IAB classification keywords lower bound',
      value: dictionaryBlockInfo.classificationKeywordsLowerbound,
      propStateName: 'classificationKeywordsLowerbound',
      min: 0,
      step: 0.01,
      max: 1,
      isFloat: true,
    },
    {
      title: 'IAB classification keywords count',
      value: dictionaryBlockInfo.classificationKeywordsCount,
      propStateName: 'classificationKeywordsCount',
      min: 0,
      step: 1,
      max: 100,
      isFloat: false,
    },
  ];

  const checkboxFormCollection = [
    {
      title: 'Enable IAB categorization algorithm',
      checked: dictionaryBlockInfo.enableIabCategorizationAlgorithm,
      propStateName: 'enableIabCategorizationAlgorithm',
    },
    {
      title: 'Enable IAB keywords merging algorithm',
      checked: dictionaryBlockInfo.enableIabKeywordsMergingAlgorithm,
      propStateName: 'enableIabKeywordsMergingAlgorithm',
    },
  ];

  const multiSelectFormCollection = [
    {
      title: 'Brand Safety categories',
      options: brandSafetyCategoriesCollection.map((item) => ({
        label: item.name,
        value: item.value,
      })),
      value: dictionaryBlockInfo.dictionaryBrandSafetyCategories.map((item) => ({
        label: item,
        value: item,
      })),
      dictionary: 'dictionaryBrandSafetyCategories',
    },
    {
      title: 'IAB classification categories',
      options: iabClassificationCategoriesCollection.map((item) => ({
        label: item.name,
        value: item.value,
      })),
      value: dictionaryBlockInfo.dictionaryIabClassificationCategories.map((item) => ({
        label: item,
        value: item,
      })),
      dictionary: 'dictionaryIabClassificationCategories',
    },
  ];

  return (
    <div className={styles.Wrapper}>
      {dictionaryBlockInfo.isLoading && (
        <div className={styles.SpinnerWrapper}>
          <CircularProgress size="large" />
        </div>
      )}
      <div className={styles.Content}>
        <Paper elevation={2} className={classNames(styles.Content_item)}>
          <Stack spacing={2}>
            {fileLoaders.map((item$) => (
              <div className={styles.Block} key={`file-single-${item$.title}`}>
                <Stack
                  direction="row"
                  alignItems="center"
                  spacing={1}
                  className={classNames(styles.Item, styles.Item___title)}
                >
                  <div>{item$.title}</div>
                  <Tooltip title={item$.description}>
                    <InfoOutlined fontSize="xSmall" htmlColor="info.main" />
                  </Tooltip>
                </Stack>
                <div className={classNames(styles.Item, styles.Item___value)}>
                  <ButtonsFileLoader
                    allowedExtensions={item$.allowedExtensions}
                    dictionary={item$.dictionary}
                    dictionaryName={item$.dictionaryName}
                    uploadConfigFileAction={() => dispatch(uploadConfigFileAction())}
                  />
                </div>
              </div>
            ))}
            {multiFileLoaders.map((item$) => (
              <div className={styles.Block} key={`file-multiple-${item$.title}`}>
                <Stack
                  direction="row"
                  alignItems="center"
                  spacing={1}
                  className={classNames(styles.Item, styles.Item___title)}
                >
                  <Typography variant="body2">{item$.title}</Typography>
                  <Tooltip title={item$.description}>
                    <InfoOutlined fontSize="xSmall" htmlColor="info.main" />
                  </Tooltip>
                </Stack>
                <div className={classNames(styles.Item, styles.Item___value)}>
                  <MultiButtonsFileLoader
                    allowedExtensions={item$.allowedExtensions}
                    dictionary={item$.dictionary}
                    dictionaryName={item$.dictionaryName}
                    uploadConfigFileAction={() => dispatch(uploadConfigFileAction())}
                  />
                </div>
              </div>
            ))}
          </Stack>
        </Paper>
        <Paper elevation={2} className={styles.Content_item}>
          <Stack spacing={2}>
            {inputsFormCollection.map((item$) => (
              <div className={styles.Block} key={`input-${item$.title}`}>
                <Typography variant="body2" className={classNames(styles.Item, styles.Item___title)}>
                  {item$.title}
                </Typography>
                <div className={classNames(styles.Item, styles.Item___value)}>
                  <TextField
                    data-id={`input-dictionary-${item$.propStateName}`}
                    type="number"
                    size="small"
                    min={item$.min}
                    step={item$.step}
                    max={item$.max}
                    value={item$.value}
                    onChange={(event) =>
                      onChangeInput({
                        min: item$.min,
                        max: item$.max,
                        isFloat: item$.isFloat,
                        fieldName: item$.propStateName,
                        value: event.target.value,
                      })
                    }
                    onBlur={(event) =>
                      onBlurInput({
                        min: item$.min,
                        max: item$.max,
                        isFloat: item$.isFloat,
                        fieldName: item$.propStateName,
                        value: event.target.value,
                      })
                    }
                  />
                </div>
              </div>
            ))}
            {checkboxFormCollection.map((item$) => (
              <div className={styles.Block} key={`checkbox-${item$.title}`}>
                <Typography variant="body2" className={classNames(styles.Item, styles.Item___title)}>
                  {item$.title}
                </Typography>
                <div className={classNames(styles.Item, styles.Item___value)}>
                  <Switch
                    size="small"
                    data-id={`checkbox-dictionary-${item$.propStateName}`}
                    checked={item$.checked}
                    onClick={() => onChangeCheckbox(item$.propStateName, !item$.checked)}
                  />
                </div>
              </div>
            ))}

            {multiSelectFormCollection.map((item$) => (
              <div className={styles.Block} key={`multi-select-${item$.title}`}>
                <Typography variant="body2" className={classNames(styles.Item, styles.Item___title)}>
                  {item$.title}
                </Typography>
                <div
                  data-id={`select-dictionary-${item$.dictionary}`}
                  className={classNames(styles.Item, styles.Item___value)}
                >
                  <Autocomplete
                    multiple
                    size="small"
                    data-id="autocomplete-keyword-list"
                    options={item$.options}
                    value={item$.value}
                    filterSelectedOptions
                    onChange={(event, elements) => {
                      dispatch(
                        updateConfigurationByPropAction({
                          [item$.dictionary]: elements.map((el) => el.label),
                        }),
                      );

                      return elements;
                    }}
                    renderInput={(params) => <TextField {...params} variant="outlined" />}
                  />
                </div>
              </div>
            ))}
            <Stack justifyContent="flex-end" direction="row">
              <Button
                data-id="button-dictionary-save"
                onClick={() =>
                  dispatch(
                    saveConfigurationDataOnServerAction([
                      'classificationIabCount',
                      'classificationIabLowerbound',
                      'classificationKeywordsLowerbound',
                      'classificationKeywordsCount',
                      'enableIabCategorizationAlgorithm',
                      'enableIabKeywordsMergingAlgorithm',
                      'dictionaryBrandSafetyCategories',
                      'dictionaryIabClassificationCategories',
                    ]),
                  )
                }
              >
                Save
              </Button>
            </Stack>
          </Stack>
        </Paper>
      </div>
    </div>
  );
}

export default Dictionary;
