import { type FC, type MouseEvent, useMemo, useState } from 'react';
import { useFormContext } from 'react-hook-form';

import { IconChevronDown } from '@material-hu/icons/tabler';
import Menu from '@material-hu/mui/Menu';
import MenuItem from '@material-hu/mui/MenuItem';
import Stack from '@material-hu/mui/Stack';
import { type SxProps, useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

import { type AutocompleteOption } from '@material-hu/components/design-system/Inputs/Autocomplete/types';
import HuTooltip from '@material-hu/components/design-system/Tooltip';

import {
  type SectionComponent,
  type TextStyles,
} from 'src/pages/dashboard/serviceManagement/types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { usePdfCompletion } from '../../contexts/PdfFormCompletionProvider';
import { TYPOGRAPHY_OVERFLOW_SX_PROPS } from '../utils/constants';
import { getFieldContainerSxProps } from '../utils/utils';

import useFieldErrorMessages from './useFieldErrorMessages';
import useFocusField from './useFocusField';

type Props = {
  field: SectionComponent;
  dimensions: {
    width: number;
    height: number;
  };
  options: AutocompleteOption[];
  textStyles: TextStyles;
};

type OptionsMenuProps = {
  id: string;
  anchorEl: HTMLElement | null;
  open: boolean;
  onClose: () => void;
  required: boolean;
  width: number;
  options: AutocompleteOption[];
  selectedValue?: string | number;
  onSelect: (value: string) => void;
  menuItemSx: SxProps;
};

const OptionsMenu: FC<OptionsMenuProps> = ({
  id,
  anchorEl,
  open,
  onClose,
  required,
  width,
  options,
  selectedValue,
  onSelect,
  menuItemSx,
}) => {
  const { t } = useLokaliseTranslation('service_management');
  return (
    <Menu
      id={id}
      anchorEl={anchorEl}
      open={open}
      onClose={onClose}
      MenuListProps={{ dense: false, sx: { py: 0 } }}
      slotProps={{
        paper: {
          elevation: 8,
          sx: { borderRadius: '4px', width: `max(${width}px, 200px)` },
        },
      }}
      anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
      transformOrigin={{ vertical: 'top', horizontal: 'left' }}
    >
      {!required && (
        <MenuItem
          onClick={() => onSelect('')}
          sx={menuItemSx}
        >
          -- {t('no_option')} --
        </MenuItem>
      )}
      {options.map(option => (
        <MenuItem
          key={option.value}
          onClick={() => onSelect(String(option.value))}
          selected={String(selectedValue ?? '') === String(option.value)}
          sx={menuItemSx}
        >
          {option.label}
        </MenuItem>
      ))}
    </Menu>
  );
};

const DropdownField: FC<Props> = ({
  field,
  dimensions,
  options,
  textStyles,
}) => {
  const {
    nameId: name,
    content: { title, required },
  } = field;

  const theme = useTheme();
  const { showErrors } = usePdfCompletion();
  const { id, handleFocus, removeFocus } = useFocusField();
  const { watch, setValue } = useFormContext();

  const answer: AutocompleteOption | undefined = watch(name);
  const hasAnswerSelected = !!answer;

  const { hasErrors, getTooltipProps } = useFieldErrorMessages({
    showErrors,
    field,
    answer,
  });

  const dimensionSxProps = {
    width: `${dimensions.width}px`,
    height: `${dimensions.height}px`,
  };

  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
  const open = Boolean(anchorEl);

  const menuItemStyles: SxProps = useMemo(
    () => ({
      ...textStyles,
      overflow: 'hidden',
      textOverflow: 'ellipsis',
      whiteSpace: 'nowrap',
      px: 1,
      color: theme.palette.new.text.neutral.default,
    }),
    [textStyles, theme.palette.new.text.neutral.default],
  );

  const handleOpenMenu = (event: MouseEvent<HTMLElement>) => {
    event.stopPropagation();
    handleFocus();
    setAnchorEl(event.currentTarget);
  };

  const handleCloseMenu = () => {
    setAnchorEl(null);
    removeFocus();
  };

  const handleSelectValue = (selectedValue: string) => {
    if (selectedValue === '') {
      setValue(name, null, {
        shouldDirty: true,
        shouldTouch: true,
        shouldValidate: true,
      });
      handleCloseMenu();
      return;
    }
    const selectedOption = options.find(
      o => String(o.value) === String(selectedValue),
    );
    setValue(name, selectedOption ?? null, {
      shouldDirty: true,
      shouldTouch: true,
      shouldValidate: true,
    });
    handleCloseMenu();
  };

  const containerSxProps = getFieldContainerSxProps(
    hasErrors,
    { width: dimensionSxProps.width, height: dimensionSxProps.height },
    theme,
  );

  if (hasAnswerSelected) {
    return (
      <>
        <HuTooltip {...getTooltipProps()}>
          <Stack
            onMouseDown={e => e.stopPropagation()}
            onClick={handleOpenMenu}
            sx={{
              position: 'relative',
              flexDirection: 'row',
              alignItems: 'center',
              justifyContent: 'space-between',
              backgroundColor: hasErrors
                ? theme.palette.new.background.feedback.error
                : theme.palette.new.background.layout.tertiary,
              ...containerSxProps,
            }}
          >
            <Typography
              sx={{
                ...TYPOGRAPHY_OVERFLOW_SX_PROPS,
                ...textStyles,
                color: ({ palette }) => palette.new.text.neutral.default,
              }}
            >
              {answer?.label ?? ''}
            </Typography>
            <IconChevronDown
              color={theme.palette.new.text.neutral.default}
              size={Math.round(textStyles.fontSize * 0.8)}
            />
          </Stack>
        </HuTooltip>
        <OptionsMenu
          id={id}
          anchorEl={anchorEl}
          open={open}
          onClose={handleCloseMenu}
          required={required}
          width={dimensions.width}
          options={options}
          selectedValue={answer?.value}
          onSelect={handleSelectValue}
          menuItemSx={menuItemStyles}
        />
      </>
    );
  }

  return (
    <>
      <HuTooltip {...getTooltipProps()}>
        <Stack
          onMouseDown={e => e.stopPropagation()}
          onClick={handleOpenMenu}
          sx={{
            position: 'relative',
            alignItems: 'center',
            gap: 0.5,
            flexDirection: 'row',
            backgroundColor: hasErrors
              ? theme.palette.new.background.feedback.error
              : theme.palette.new.background.layout.brand,
            ...containerSxProps,
          }}
        >
          <Typography
            sx={{
              ...TYPOGRAPHY_OVERFLOW_SX_PROPS,
              ...textStyles,
              color: ({ palette }) => palette.new.text.neutral.default,
            }}
          >
            {title}
          </Typography>
          {required && (
            <Typography
              sx={{
                ...textStyles,
                color: ({ palette }) => palette.new.text.feedback.error,
              }}
            >
              *
            </Typography>
          )}
        </Stack>
      </HuTooltip>
      <OptionsMenu
        id={id}
        anchorEl={anchorEl}
        open={open}
        onClose={handleCloseMenu}
        required={required}
        width={dimensions.width}
        options={options}
        selectedValue={undefined}
        onSelect={handleSelectValue}
        menuItemSx={menuItemStyles}
      />
    </>
  );
};

export default DropdownField;
