import { useEffect, useState } from 'react';
import { useFormContext } from 'react-hook-form';

import ClickAwayListener from '@material-hu/mui/ClickAwayListener';
import Paper from '@material-hu/mui/Paper';
import Popper from '@material-hu/mui/Popper';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuFormCheckbox from '@material-hu/components/design-system/Checkbox/Checkbox/form';
import HuChips from '@material-hu/components/design-system/Chip';
import HuFormSearch from '@material-hu/components/design-system/Inputs/Search/form';
import HuMenuItem from '@material-hu/components/design-system/Menu/components/MenuItem';
import HuTitle from '@material-hu/components/design-system/Title';

import { useLokaliseTranslation } from 'src/utils/i18n';

export type Option = {
  id: number;
  label: string;
  description: string;
  checked: boolean;
  disabled?: boolean;
  info?: string;
};

export type CheckboxAutocompleteProps = {
  name: string;
  label: string;
  options: Option[];
  disabled?: boolean;
  uncheckedDisabled?: boolean;
  searchLoading?: boolean;
  searchDisabled?: boolean;
  searchEmpty?: boolean;
  helperText?: string;
};

export const CheckboxAutocomplete = ({
  name,
  label,
  options,
  disabled = false,
  uncheckedDisabled = false,
  searchLoading = false,
  searchDisabled = false,
  searchEmpty = false,
  helperText,
}: CheckboxAutocompleteProps) => {
  const [anchorEl, setAnchorEl] = useState(null);
  const [containerEl, setContainerEl] = useState(null);
  const showMenu = !searchDisabled && Boolean(anchorEl);

  const { t } = useLokaliseTranslation('libraries');

  const { setValue, watch } = useFormContext();

  const selected = watch(name);

  useEffect(() => {
    if (searchDisabled) setAnchorEl(null);
  }, [searchDisabled]);

  const handleSearchFocus = () => {
    const container = document.querySelector(
      '#checkbox-autocomplete-search-input',
    );
    const input = document.querySelector(
      '#checkbox-autocomplete-search-input .MuiInputBase-root',
    );
    setAnchorEl(input);
    setContainerEl(container);
  };

  const isChecked = (option: Option) => {
    if (!selected || !option) return false;
    return option.checked || selected.some(v => v.id === option.id);
  };

  const isDisabled = (option: Option) => {
    if (!option) return false;
    return option.disabled || (uncheckedDisabled && !isChecked(option));
  };

  const handleDelete = (option: Option) =>
    setValue(
      name,
      selected.filter(v => v.id !== option.id),
    );

  const handleAdd = (option: Option) =>
    setValue(name, [...selected, { ...option, checked: true }]);

  const handleToggle = (item: any) =>
    isChecked(item) ? handleDelete(item) : handleAdd(item);

  const handleClickAway = (event: Event) => {
    if (anchorEl.contains(event.target)) return;
    setAnchorEl(null);
  };

  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
    if (event.key === 'Escape' || event.key === 'Tab') {
      setAnchorEl(null);
    }
  };

  const isMenuOverflow = (height: number) => {
    if (!containerEl || !height) return false;

    const menuTop = containerEl.offsetHeight + containerEl.offsetTop;
    const menuBottom = menuTop + height;
    const parentHeight = containerEl.offsetParent.offsetHeight;

    return menuBottom > parentHeight;
  };

  const getMenuHeight = () => {
    const itemHeight = 75.6;
    const maxHeight = itemHeight * 5;
    const minHeight = itemHeight * 3;
    return !isMenuOverflow(maxHeight) ? maxHeight : minHeight;
  };

  return (
    <Stack
      onKeyDown={handleKeyDown}
      sx={{
        gap: 2,
        p: 2,
        borderRadius: 2,
        backgroundColor: theme => theme.palette.hugoBackground.neutralBg,
      }}
    >
      <Stack id="checkbox-autocomplete-search-input">
        <HuFormSearch
          name="search"
          inputProps={{
            disabled: searchDisabled,
            loading: searchLoading,
            label,
            helperText,
            autoFocus: true,
            onFocus: handleSearchFocus,
          }}
        />
      </Stack>
      <Popper
        open={showMenu}
        anchorEl={anchorEl}
        modifiers={[
          {
            name: 'preventOverflow',
            enabled: true,
            options: {
              altAxis: true,
              altBoundary: true,
              tether: true,
              rootBoundary: 'viewport',
              padding: 8,
            },
          },
        ]}
        sx={{
          zIndex: 2000,
          width: anchorEl?.clientWidth,
          maxHeight: getMenuHeight(),
        }}
      >
        <ClickAwayListener onClickAway={handleClickAway}>
          <Paper
            sx={{
              maxHeight: getMenuHeight(),
              overflow: 'auto',
            }}
          >
            {(searchLoading || searchEmpty) && (
              <Stack sx={{ p: 2 }}>
                {searchLoading && (
                  <HuTitle
                    variant="S"
                    title={t('general:loading')}
                  />
                )}
                {searchEmpty && (
                  <HuTitle
                    variant="S"
                    title={t('general:empty_search_result')}
                  />
                )}
              </Stack>
            )}
            {options?.map(option => (
              <HuMenuItem
                key={option.id}
                onClick={() => handleToggle(option)}
                disabled={isDisabled(option)}
                sx={{
                  '&.Mui-disabled': {
                    opacity: 'unset',
                  },
                }}
              >
                <HuFormCheckbox
                  name={`options.${name}.${option.id}`}
                  checkBoxProps={{
                    label: option.label,
                    description: option.description,
                    checked: isChecked(option),
                    disabled: isDisabled(option),
                  }}
                />
                <Typography
                  variant="globalXS"
                  sx={{
                    alignSelf: 'flex-start',
                    ml: 'auto',
                    color: theme =>
                      theme.palette.textColors.neutralTextDisabled,
                  }}
                >
                  {option.info}
                </Typography>
              </HuMenuItem>
            ))}
          </Paper>
        </ClickAwayListener>
      </Popper>
      <Stack
        sx={{
          flexDirection: 'row',
          flexWrap: 'wrap',
          gap: 1,
        }}
      >
        {selected.map(option => (
          <HuChips
            key={option.id}
            label={option.label}
            onDelete={() => handleDelete(option)}
            disabled={disabled}
          />
        ))}
      </Stack>
    </Stack>
  );
};

export default CheckboxAutocomplete;
