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

import { zodResolver } from '@hookform/resolvers/zod';

import useSnackbar from '@material-hu/components/design-system/Snackbar';
import { Drawer, useDrawerLayer } from '@material-hu/components/layers/Drawers';

import {
  useClearMoodMutation,
  useCurrentMoodQuery,
} from 'src/hooks/useUserMood';
import { useLokaliseTranslation } from 'src/utils/i18n';

import MoodStatusForm from './MoodStatusForm';
import { createMoodFormSchema } from './schemas';
import { type MoodFormValues } from './types';
import { useSetMoodMutation } from './useSetMoodMutation';
import { computeExpiresAt } from './utils/dates';
import { getDefaultValues } from './utils/values';

const MoodStatusFormDrawer = () => {
  const { t } = useLokaliseTranslation('user_mood');
  const { enqueueSnackbar } = useSnackbar();
  const { closeDrawer } = useDrawerLayer();

  const { data: mood } = useCurrentMoodQuery();
  const isEditing = mood != null;

  const { mutate: setMoodMutate, isLoading: isSaving } = useSetMoodMutation();
  const { mutate: clearMoodMutate, isLoading: isClearing } =
    useClearMoodMutation();

  // `values` keeps the form in sync with the loaded mood without an explicit
  // reset(); `keepDirtyValues` protects in-progress edits from background
  // refetches.
  const form = useForm<MoodFormValues>({
    resolver: zodResolver(createMoodFormSchema(t)),
    values: getDefaultValues(mood),
    resetOptions: { keepDirtyValues: true },
  });
  const { control } = form;

  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 customTime = useWatch({ control, name: 'customTime' });
  const { isDirty } = form.formState;

  // For "custom" both date and time are required and the resulting datetime
  // must be in the future (otherwise the mood would be saved already expired).
  const customExpiresAt =
    duration === 'custom'
      ? computeExpiresAt('custom', customDate, customTime)
      : null;
  const isCustomValid =
    customExpiresAt != null && new Date(customExpiresAt).getTime() > Date.now();

  const isComplete =
    !!emoji &&
    !!description.trim() &&
    !!duration &&
    (duration !== 'custom' || isCustomValid);
  // Clearing every field while editing turns "Guardar" into a delete action.
  const isClearedWhileEditing =
    isEditing && !emoji && !description.trim() && !duration;

  const canSave = isComplete || isClearedWhileEditing;
  // In edit mode the button stays disabled until the user changes something.
  const isSaveDisabled = !canSave || (isEditing && !isDirty);

  // The trash clears every field; with an empty form while editing, "Guardar"
  // deletes the mood.
  const handleClear = () => {
    form.setValue('emoji', '', { shouldDirty: true });
    form.setValue('description', '', { shouldDirty: true });
    form.setValue('duration', null, { shouldDirty: true });
    form.setValue('customDate', null, { shouldDirty: true });
    form.setValue('customTime', null, { shouldDirty: true });
  };

  const deleteMood = () => {
    clearMoodMutate(undefined, {
      onSuccess: () => {
        enqueueSnackbar({
          title: t('user_mood:clear_success'),
          variant: 'success',
        });
        closeDrawer();
      },
    });
  };

  const saveMood = form.handleSubmit(values => setMoodMutate(values));

  const handleSave = () => {
    if (isClearedWhileEditing) {
      deleteMood();
      return;
    }
    saveMood();
  };

  return (
    <FormProvider {...form}>
      <Drawer.Header
        title={t('update_status')}
        onClose={() => closeDrawer()}
      />
      <Drawer.Body>
        <MoodStatusForm
          isEditing={isEditing}
          onDelete={handleClear}
        />
      </Drawer.Body>
      <Drawer.Actions
        primaryButtonProps={{
          fullWidth: true,
          children: t('general:save'),
          disabled: isSaveDisabled,
          loading: isSaving || isClearing,
          onClick: handleSave,
        }}
      />
    </FormProvider>
  );
};

export default MoodStatusFormDrawer;
