import { Fragment, useState } from 'react';
import { useMutation, useQuery } from 'react-query';
import { Link as RouterLink } from 'react-router-dom';

import bluebird from 'bluebird';
import { difference, uniq, without } from 'lodash-es';
import ExpandMoreIcon from '@material-hu/icons/material/ExpandMore';
import HelpOutlineIcon from '@material-hu/icons/material/HelpOutline';
import Accordion from '@material-hu/mui/Accordion';
import AccordionDetails from '@material-hu/mui/AccordionDetails';
import AccordionSummary from '@material-hu/mui/AccordionSummary';
import Backdrop from '@material-hu/mui/Backdrop';
import Checkbox from '@material-hu/mui/Checkbox';
import DialogActions from '@material-hu/mui/DialogActions';
import DialogContent from '@material-hu/mui/DialogContent';
import DialogTitle from '@material-hu/mui/DialogTitle';
import Link from '@material-hu/mui/Link';
import List from '@material-hu/mui/List';
import ListItem from '@material-hu/mui/ListItem';
import ListItemButton from '@material-hu/mui/ListItemButton';
import ListItemIcon from '@material-hu/mui/ListItemIcon';
import ListItemText from '@material-hu/mui/ListItemText';
import ListSubheader from '@material-hu/mui/ListSubheader';
import Tab from '@material-hu/mui/Tab';
import Tabs from '@material-hu/mui/Tabs';
import Tooltip from '@material-hu/mui/Tooltip';
import Typography from '@material-hu/mui/Typography';

import Button from '@material-hu/components/design-system/Buttons/Button';

import { onboardingsRoutes } from 'src/pages/dashboard/Onboardings/routes';
import * as onboardingsService from 'src/services/onboardingsService';
import { type OnboardingTaskLibrary } from 'src/types/onboarding';
import { addOrRemove } from 'src/utils/arrayUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { formatSimpleDateString } from 'src/utils/timeUtils';

import CenteredCircularProgress from 'src/components/CircularProgress';

import { usersKeys } from '../../../queries';

import NoTasks from './NoTasks';

type Props = {
  closeModal: () => void;
  refetch: Function;
  userId: number;
};

const AddTasks = ({ closeModal, refetch, userId }: Props) => {
  const { t } = useLokaliseTranslation('users');

  const [selected, setSelected] = useState([]);

  const categoriesWithNoAutoassignParams = {
    willBeAutoAssigned: false,
    matchesSegmentation: true,
  };
  const {
    data: categoriesWithNoAutoassign,
    isLoading: categoriesWithNoAutoassignLoading,
  } = useQuery(
    usersKeys.userOnboardingTasks(userId, categoriesWithNoAutoassignParams),
    () =>
      onboardingsService.getUserTaskLibrary(
        userId,
        categoriesWithNoAutoassignParams,
      ),
    { select: response => response.data },
  );

  const categoriesWithAutoassignParams = { willBeAutoAssigned: true };
  const {
    data: categoriesWithAutoassign,
    isLoading: categoriesWithAutoassignLoading,
  } = useQuery(
    usersKeys.userOnboardingTasks(userId, categoriesWithAutoassignParams),
    () =>
      onboardingsService.getUserTaskLibrary(
        userId,
        categoriesWithAutoassignParams,
      ),
    { select: response => response.data },
  );

  const noApplyCategoriesParams = { matchesSegmentation: false };
  const { data: noApplyCategories, isLoading: noApplyCategoriesLoading } =
    useQuery(
      usersKeys.userOnboardingTasks(userId, noApplyCategoriesParams),
      () =>
        onboardingsService.getUserTaskLibrary(userId, noApplyCategoriesParams),
      { select: response => response.data },
    );

  const assignTasksMutation = useMutation(
    async () => {
      await bluebird.each(selected, taskId =>
        onboardingsService.assignUserOnboardingTasks(userId, taskId),
      );
      return refetch();
    },
    {
      onSettled: () => {
        closeModal();
      },
    },
  );

  const [tabIndex, setTabIndex] = useState(0);

  if (
    categoriesWithNoAutoassignLoading ||
    noApplyCategoriesLoading ||
    categoriesWithAutoassignLoading
  ) {
    return (
      <Backdrop open>
        <CenteredCircularProgress centered />
      </Backdrop>
    );
  }

  const showingAplicable = !tabIndex;
  const currentCategories = showingAplicable
    ? categoriesWithNoAutoassign
    : noApplyCategories;

  const hasTasks = !!currentCategories.length;
  const assignableTasksIds = currentCategories.flatMap(({ tasks }) =>
    tasks.filter(({ assigned }) => !assigned).map(({ id }) => id),
  );
  const allAreSelected = !difference(assignableTasksIds, selected).length;

  function SelectAll() {
    if (!assignableTasksIds.length) {
      return null;
    }
    return (
      <Button
        size="small"
        onClick={() =>
          setSelected(s =>
            allAreSelected
              ? without(s, ...assignableTasksIds)
              : uniq([...s, ...assignableTasksIds]),
          )
        }
        sx={{ mt: 2 }}
      >
        {t(allAreSelected ? 'DESELECT_ALL' : 'SELECT_ALL')}
      </Button>
    );
  }

  const hasAutoassignTasks = !!categoriesWithAutoassign.length;

  function getTaskList(
    list: OnboardingTaskLibrary[],
    showAutoAssignDate = false,
  ) {
    return (
      <List>
        {list.map(category => (
          <Fragment key={category.id}>
            <ListSubheader>{category.name}</ListSubheader>
            {category.tasks.map(task => {
              const disabled = task.assigned;
              const checked = task.assigned || selected.includes(task.id);
              const handleClick = () =>
                !disabled && setSelected(s => addOrRemove(s, task.id));

              return (
                <ListItem
                  key={task.id}
                  dense
                  disablePadding
                  title={t('AUTO_ASSIGN_TOOLTIP')}
                >
                  <ListItemButton
                    dense
                    onClick={handleClick}
                    disabled={disabled}
                  >
                    <ListItemIcon>
                      <Checkbox
                        edge="start"
                        checked={checked}
                        disableRipple
                      />
                    </ListItemIcon>
                    <ListItemText
                      primary={task.name}
                      secondary={
                        showAutoAssignDate &&
                        t('AUTO_ASSIGN_DATE', {
                          date: formatSimpleDateString(
                            task.autoAssignDate as unknown as string,
                          ),
                        })
                      }
                    />
                  </ListItemButton>
                </ListItem>
              );
            })}
          </Fragment>
        ))}
      </List>
    );
  }

  return (
    <>
      <DialogTitle>{t('TASKS_LIBRARY')}</DialogTitle>
      <DialogContent>
        <Tabs
          value={tabIndex}
          onChange={(e, index) => setTabIndex(index)}
          variant="fullWidth"
          sx={{ borderBottomStyle: 'solid', borderColor: 'divider' }}
        >
          <Tab
            label={t('MATCHING_TASKS')}
            icon={
              <Tooltip title={t('MATCHING_TASKS_TOOLTIP')}>
                <HelpOutlineIcon fontSize="small" />
              </Tooltip>
            }
            iconPosition="end"
            sx={{ minHeight: 0 }}
          />
          <Tab
            label={t('NO_MATCHING_TASKS')}
            icon={
              <Tooltip title={t('NO_MATCHING_TASKS_TOOLTIP')}>
                <HelpOutlineIcon fontSize="small" />
              </Tooltip>
            }
            iconPosition="end"
            sx={{ minHeight: 0 }}
          />
        </Tabs>
        {hasTasks && (
          <>
            <SelectAll />
            {getTaskList(currentCategories)}
          </>
        )}
        {showingAplicable && hasAutoassignTasks && (
          <Accordion
            sx={{
              boxShadow: 'none',
              ':before': { display: 'none' },
            }}
          >
            <AccordionSummary
              expandIcon={<ExpandMoreIcon />}
              sx={{ px: 0 }}
            >
              <Typography sx={{ fontWeight: 'bold' }}>
                {`${t('AUTO_ASSIGN_TASKS')} ⚡`}
              </Typography>
            </AccordionSummary>
            <AccordionDetails sx={{ px: 0 }}>
              {getTaskList(categoriesWithAutoassign, true)}
            </AccordionDetails>
          </Accordion>
        )}
        {!hasTasks && (!showingAplicable || !hasAutoassignTasks) && (
          <NoTasks
            sx={{ mt: 2 }}
            title={t(
              showingAplicable
                ? 'NO_APPLICABLE_TASKS'
                : 'NO_NON_APPLICABLE_TASKS',
            )}
            subtitle={
              showingAplicable && (
                <Typography>
                  {t('NO_TASKS_1')}
                  <Link
                    component={RouterLink}
                    to={onboardingsRoutes.base()}
                  >
                    {t('NO_TASKS_2')}
                  </Link>
                  {t('NO_TASKS_3')}
                </Typography>
              )
            }
          />
        )}
      </DialogContent>
      <DialogActions>
        <Button
          loading={assignTasksMutation.isLoading}
          variant="contained"
          onClick={() => assignTasksMutation.mutate()}
          disabled={!selected.length}
        >
          {t('ASSIGN')}
        </Button>
      </DialogActions>
    </>
  );
};
export default AddTasks;
