import { useEffect, useMemo, useRef, useState } from 'react';

import AddIcon from '@material-hu/icons/material/Add';
import { IconX } from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import Button from '@material-hu/components/design-system/Buttons/Button';
import HuSwitcher from '@material-hu/components/design-system/Switcher';
import HuTooltip from '@material-hu/components/design-system/Tooltip';

import { PollState } from 'src/types/feed';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';

import FormTextField from 'src/components/FormInputs/FormTextField';
import PollDeadlineForm from 'src/components/poll/PollDeadlineForm';

export type UsePollCreateStateProps = {
  min?: number;
  max?: number;
  options?: string[];
  votersVisible?: boolean;
  deadlineEnabled?: boolean;
  endsAt?: Date | null;
  isSubmitting?: boolean;
  pollState?: PollState;
  onSave?: (
    options: string[],
    votersVisible: boolean,
    deadlineEnabled: boolean,
    endsAt: Date | null,
  ) => void;
  onChange?: (
    options: string[],
    votersVisible: boolean,
    deadlineEnabled: boolean,
    endsAt: Date | null,
  ) => void;
};

const CHARACTER_LIMIT = 100;

export function usePollCreateState(props: UsePollCreateStateProps) {
  const {
    min = 2,
    max = 4,
    options: propOptions = [],
    votersVisible = false,
    deadlineEnabled = false,
    endsAt = null,
    isSubmitting = false,
    pollState = {
      form: { disabled: false, message: '' },
      cancel: { disabled: false, message: '' },
    },
    onSave,
    onChange,
  } = props;

  const options = useMemo(
    () =>
      propOptions.length > 0
        ? propOptions
            .filter(option => option != null)
            .map(option => String(option))
        : Array.from(Array(min), () => ''),
    [propOptions, min],
  );

  const isFormDisabled = isSubmitting || pollState.form.disabled;
  const isCancelDisabled = isSubmitting || pollState.cancel.disabled;

  // Check if poll can be saved (all options must be filled, with at least min options)
  const validOptions = options.filter(option => option.trim().length > 0);
  const hasEmptyOptions = options.some(option => option.trim().length === 0);
  const isDeadlineValid = !deadlineEnabled || (endsAt && endsAt > new Date());
  const canSave =
    validOptions.length >= min &&
    !hasEmptyOptions &&
    !isFormDisabled &&
    isDeadlineValid;

  const handleSave = () => {
    if (onSave && canSave) {
      onSave(options, votersVisible, deadlineEnabled, endsAt);
    }
  };

  const updateOptions = (newOptions: string[]) => {
    if (onChange) {
      onChange(newOptions, votersVisible, deadlineEnabled, endsAt);
    }
  };

  const updateVotersVisible = (newVotersVisible: boolean) => {
    if (onChange) {
      onChange(options, newVotersVisible, deadlineEnabled, endsAt);
    }
  };

  const updateDeadlineEnabled = (newDeadlineEnabled: boolean) => {
    if (onChange) {
      onChange(options, votersVisible, newDeadlineEnabled, endsAt);
    }
  };

  const updateEndsAt = (newEndsAt: Date | null) => {
    if (onChange) {
      onChange(options, votersVisible, deadlineEnabled, newEndsAt);
    }
  };

  return {
    options,
    updateOptions,
    votersVisible,
    updateVotersVisible,
    deadlineEnabled,
    updateDeadlineEnabled,
    endsAt,
    updateEndsAt,
    isFormDisabled,
    isCancelDisabled,
    canSave,
    handleSave,
    min,
    max,
  };
}

const PollCreateDrawerContent = (props: {
  pollCreateState: ReturnType<typeof usePollCreateState>;
  pollState?: PollState;
}) => {
  const { pollCreateState, pollState } = props;
  const {
    options,
    updateOptions,
    votersVisible,
    updateVotersVisible,
    deadlineEnabled,
    updateDeadlineEnabled,
    endsAt,
    updateEndsAt,
    isFormDisabled,
    min,
    max,
  } = pollCreateState;

  const [focusedIndex, setFocusedIndex] = useState<number | null>(null);
  const firstInputRef = useRef<HTMLInputElement | null>(null);

  const handleChangeOption =
    (index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
      const { value } = e.target;
      const newOptions = [...options];
      newOptions[index] = value;
      updateOptions(newOptions);
    };

  const addOption = (): void => {
    if (options.length < max) {
      updateOptions([...options, '']);
    }
  };

  const deleteOption = (index: number): void => {
    if (options.length > min) {
      const newOptions = [...options];
      newOptions.splice(index, 1);
      updateOptions(newOptions);
      setFocusedIndex(null);
    }
  };

  const handleVotersVisibilityChange = (checked: boolean): void => {
    updateVotersVisible(checked);
  };

  const { t } = useTranslation('post');

  useEffect(() => {
    if (firstInputRef.current && !isFormDisabled) {
      firstInputRef.current.focus();
      setFocusedIndex(0);
    }
  }, [isFormDisabled]);

  return (
    <Stack>
      {isFormDisabled && pollState?.form.message && (
        <Box sx={{ mb: 2 }}>
          <Typography
            variant="globalXS"
            sx={{
              color: theme => theme.palette.new.text.neutral.disabled,
            }}
          >
            {pollState.form.message}
          </Typography>
        </Box>
      )}

      <Stack sx={{ gap: 0.5, mb: 1 }}>
        {options.map((option, index) => (
          <Box
            key={`${index}-${options.length}`}
            sx={{
              display: 'flex',
              flexDirection: 'row',
              position: 'relative',
              alignItems: 'center',
            }}
          >
            <FormTextField
              name={`pollOption_${index}`}
              aria-label={t('add_option_label')}
              placeholder={t('add_option_placeholder', {
                index: index + 1,
              })}
              size="small"
              fullWidth
              variant="outlined"
              disabled={isFormDisabled}
              helperText={
                <span
                  style={{
                    display: 'flex',
                    justifyContent: 'right',
                    height: '1.5em',
                  }}
                >
                  {focusedIndex === index
                    ? `${option.length}/${CHARACTER_LIMIT}`
                    : ''}
                </span>
              }
              inputProps={{ maxLength: CHARACTER_LIMIT }}
              InputProps={{
                endAdornment: options.length > min &&
                  focusedIndex === index && (
                    <HuTooltip
                      title={t('post:delete_web')}
                      direction="top"
                    >
                      <span>
                        <IconButton
                          onMouseDown={() => deleteOption(index)}
                          disabled={isFormDisabled || options.length <= min}
                          sx={{
                            '&:hover': { backgroundColor: 'transparent' },
                            color: theme =>
                              theme.palette.new.text.neutral.default,
                            pr: 0,
                          }}
                        >
                          <IconX />
                        </IconButton>
                      </span>
                    </HuTooltip>
                  ),
              }}
              value={option}
              onChange={handleChangeOption(index)}
              onFocus={() => !isFormDisabled && setFocusedIndex(index)}
              onBlur={() => !isFormDisabled && setFocusedIndex(null)}
              inputRef={index === 0 ? firstInputRef : undefined}
              sx={{
                borderRadius: 1,
                '& .MuiInputBase-root': {
                  '& .MuiInputBase-input': {
                    p: 2,
                  },
                  borderRadius: 1,
                },
              }}
            />
          </Box>
        ))}
      </Stack>

      {options.length < max && (
        <Box sx={{ mb: 3 }}>
          <Button
            fullWidth
            variant="outlined"
            size="small"
            startIcon={<AddIcon />}
            onClick={addOption}
            disabled={isFormDisabled || options.length >= max}
          >
            {t('post:add_option_web')}
          </Button>
        </Box>
      )}

      <Stack
        sx={{
          p: 2,
          backgroundColor: theme => theme.palette.new.background.layout.default,
          borderRadius: theme => theme.shape.borderRadiusL,
          mb: 2,
        }}
      >
        <Stack
          direction="row"
          alignItems="center"
        >
          <HuSwitcher
            title={t('hide_voters')}
            description={t('hide_voters_description')}
            value={!votersVisible}
            onChange={() => handleVotersVisibilityChange(!votersVisible)}
            disabled={isFormDisabled}
          />
        </Stack>
      </Stack>

      <PollDeadlineForm
        deadlineEnabled={deadlineEnabled}
        endsAt={endsAt}
        onDeadlineEnabledChange={updateDeadlineEnabled}
        onEndsAtChange={updateEndsAt}
        disabled={isFormDisabled}
      />
    </Stack>
  );
};

export const getPollCreateDrawerConfig = (
  pollCreateState: ReturnType<typeof usePollCreateState>,
  closeDrawer: () => void,
  title?: string,
  onCancel?: () => void,
  pollState?: PollState,
) => {
  const { t } = useTranslation('post');
  const { canSave, isCancelDisabled, handleSave } = pollCreateState;

  return {
    title,
    primaryButtonProps: {
      children: t('save'),
      fullWidth: true,
      disabled: !canSave,
      onClick: () => {
        handleSave();
        closeDrawer();
      },
    },
    secondaryButtonProps: {
      children: t('cancel'),
      fullWidth: true,
      disabled: isCancelDisabled,
      onClick: () => {
        onCancel?.();
        closeDrawer();
      },
    },
    children: (
      <PollCreateDrawerContent
        pollCreateState={pollCreateState}
        pollState={pollState}
      />
    ),
    onClose: () => {
      onCancel?.();
      closeDrawer();
    },
  };
};

export default PollCreateDrawerContent;
