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

import { IconMoodSmile, IconTrash } from '@material-hu/icons/tabler';
import Divider from '@material-hu/mui/Divider';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

import FormTimePicker from '@material-hu/components/composed-components/TimePicker/form';
import Chip from '@material-hu/components/design-system/Chip';
import IconSelector from '@material-hu/components/design-system/IconSelector';
import FormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import FormDatePicker from '@material-hu/components/design-system/Inputs/DatePicker/form';
import ListItem from '@material-hu/components/design-system/List/components/ListItem';

import { type MoodDurationPreset } from 'src/types/userMood';
import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  DURATION_PRESETS,
  durationLabelKey,
  MOOD_TEMPLATES,
} from './constants';
import { type MoodFormValues } from './types';

type Props = {
  isEditing: boolean;
  onDelete: () => void;
};

const MOOD_ICON_TRIGGER_SIZE = 7;
const CUSTOM_TIME_OFFSET_MS = 10 * 60_000;
const DESCRIPTION_MAX_LENGTH = 100;
const DESCRIPTION_MAX_ROWS = 4;

const setOptions = { shouldValidate: true, shouldDirty: true } as const;

const MoodStatusForm = ({ isEditing, onDelete }: Props) => {
  const { t } = useLokaliseTranslation('user_mood');
  const theme = useTheme();
  const {
    control,
    setValue,
    getValues,
    formState: { isDirty },
  } = useFormContext<MoodFormValues>();
  const iconTriggerSize = theme.spacing(MOOD_ICON_TRIGGER_SIZE);

  const emoji = useWatch({ control, name: 'emoji' });
  const description = useWatch({ control, name: 'description' });
  const duration = useWatch({ control, name: 'duration' });
  const customDate = useWatch({ control, name: 'customDate' });

  const isAtCharLimit = description.length >= DESCRIPTION_MAX_LENGTH;
  // When the custom date is today, block picking a time earlier than now.
  const isCustomDateToday =
    !customDate || customDate.toDateString() === new Date().toDateString();

  // Custom date/time are pre-filled (today + now + 10 min) so the form is not
  // left in an empty-required state when "Personalizado" is selected.
  const selectDuration = (preset: MoodDurationPreset) => {
    setValue('duration', preset, setOptions);
    if (preset !== 'custom') return;
    if (!getValues('customDate')) {
      setValue('customDate', new Date(), setOptions);
    }
    if (!getValues('customTime')) {
      setValue(
        'customTime',
        new Date(Date.now() + CUSTOM_TIME_OFFSET_MS),
        setOptions,
      );
    }
  };

  const applyTemplate = (
    templateEmoji: string,
    labelKey: string,
    preset: MoodDurationPreset,
  ) => {
    setValue('emoji', templateEmoji, setOptions);
    setValue('description', t(labelKey), setOptions);
    selectDuration(preset);
  };

  return (
    <Stack sx={{ gap: 3 }}>
      <Stack sx={{ flexDirection: 'row', gap: 1, alignItems: 'flex-start' }}>
        <IconSelector
          mode="emoji"
          icon={
            emoji ? (
              <Stack sx={{ fontSize: 24, lineHeight: 1 }}>{emoji}</Stack>
            ) : (
              <IconMoodSmile />
            )
          }
          onEmojiSelect={({ emoji: selected }) =>
            setValue('emoji', selected, setOptions)
          }
          slotProps={{
            iconButton: {
              variant: 'secondary',
              size: 'large',
              sx: {
                width: iconTriggerSize,
                height: iconTriggerSize,
                flexShrink: 0,
                m: 0,
              },
            },
          }}
        />
        <Stack sx={{ flex: 1, minWidth: 0 }}>
          <FormInputClassic
            name="description"
            inputProps={{
              placeholder: t('user_mood:status_placeholder'),
              maxLength: DESCRIPTION_MAX_LENGTH,
              hasCounter: isAtCharLimit,
              error: isAtCharLimit,
              errorText: isAtCharLimit
                ? t('user_mood:char_limit_reached')
                : undefined,
              multiline: true,
              minRows: 1,
              maxRows: DESCRIPTION_MAX_ROWS,
              showClear: false,
              sxInput: {
                minHeight: iconTriggerSize,
                alignItems: 'flex-start',
              },
            }}
          />
        </Stack>
        <IconButton
          aria-label={t('general:delete')}
          onClick={onDelete}
          variant="secondary"
          disabled={!isEditing && !isDirty}
          sx={{
            width: iconTriggerSize,
            height: iconTriggerSize,
            flexShrink: 0,
          }}
        >
          <IconTrash />
        </IconButton>
      </Stack>

      <Stack sx={{ gap: 1 }}>
        <Typography
          variant="globalS"
          fontWeight="fontWeightSemiBold"
        >
          {t('user_mood:remove_after')}
        </Typography>
        <Stack sx={{ flexDirection: 'row', flexWrap: 'wrap', gap: 1 }}>
          {DURATION_PRESETS.map(preset => (
            <Chip
              key={preset.value}
              label={t(preset.labelKey)}
              isSelected={duration === preset.value}
              onClick={() => selectDuration(preset.value)}
            />
          ))}
        </Stack>
        {duration === 'custom' && (
          <Stack sx={{ flexDirection: 'row', gap: 1 }}>
            <Stack sx={{ flex: 1 }}>
              <FormDatePicker
                name="customDate"
                inputProps={{ disablePast: true }}
              />
            </Stack>
            <Stack sx={{ flex: 1 }}>
              <FormTimePicker
                name="customTime"
                inputProps={{ disablePast: isCustomDateToday }}
              />
            </Stack>
          </Stack>
        )}
      </Stack>

      <Divider />

      <Stack sx={{ gap: 1 }}>
        <Typography
          variant="globalS"
          fontWeight="fontWeightSemiBold"
        >
          {t('user_mood:suggestions')}
        </Typography>
        {MOOD_TEMPLATES.map(template => (
          <ListItem
            key={template.id}
            onClick={() =>
              applyTemplate(
                template.emoji,
                template.labelKey,
                template.duration,
              )
            }
            avatar={{ text: template.emoji }}
            text={{ title: t(template.labelKey) }}
            sideText={{
              title:
                template.duration === 'custom'
                  ? t(durationLabelKey(template.duration)).toLowerCase()
                  : t(durationLabelKey(template.duration)),
            }}
            slotProps={{
              container: { sx: { pr: 0.5, pl: 0, py: 0, my: 0.5 } },
              avatar: {
                sx: {
                  '& .MuiTypography-root': {
                    fontSize: 24,
                    lineHeight: 1,
                  },
                },
              },
            }}
          />
        ))}
      </Stack>
    </Stack>
  );
};

export default MoodStatusForm;
