/** biome-ignore-all lint/correctness/useHookAtTopLevel: This hook is used in useDrawerV2 */
import { useCallback, useEffect, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation, useQueryClient } from 'react-query';

import Stack from '@material-hu/mui/Stack';

import HTMLBody from '@material-hu/components/composed-components/HTMLBody';
import { type DrawerProps } from '@material-hu/components/design-system/Drawer';
import FormTextArea from '@material-hu/components/design-system/Inputs/TextArea/form';
import useSnackbar from '@material-hu/components/design-system/Snackbar';

import { useUnsavedWarning } from 'src/hooks/useUnsavedWarning';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { requiredLabel } from 'src/utils/stringUtils';

import { ModalUnsavedChanges } from '../../../components/ModalUnsavedChanges';
import { applicantsKeys } from '../../../queries';
import {
  createApplicationStageNote,
  updateApplicationStageNote,
} from '../../../services';
import {
  type ApplicationNote,
  type NoteFormValues,
  type User,
} from '../../../types';
import { noteFormResolver } from '../utils';

type UseNotesDrawerContentProps = {
  onClose: () => void;
  applicationId: number;
  jobId: number;
};

type DrawerOpenProps = {
  note?: ApplicationNote;
  stageId: number;
  open: boolean;
  user?: User;
};

export const useNotesDrawerContent =
  ({ onClose, applicationId, jobId }: UseNotesDrawerContentProps) =>
  ({ note, open, user, stageId }: DrawerOpenProps) => {
    const { t } = useLokaliseTranslation(['ats', 'general', 'validations']);
    const { enqueueSnackbar } = useSnackbar();
    const queryClient = useQueryClient();

    const [shouldShowTextArea, setShouldShowTextArea] = useState(false);

    const isOwnNote = useMemo(() => {
      if (!note) return true;
      return note.userId === user?.id;
    }, [note, user?.id]);

    const resolver = useMemo(
      () => (values: Partial<NoteFormValues>) => noteFormResolver(values, t),
      [t],
    );

    const form = useForm<NoteFormValues>({
      mode: 'onChange',
      defaultValues: {
        note: note?.content || '',
      },
      resolver,
    });

    const resetForm = useCallback(
      (values: NoteFormValues) => {
        form.reset(values, {
          keepDirty: false,
          keepIsValid: false,
          keepErrors: false,
        });
      },
      [form],
    );

    useEffect(() => {
      if (open) {
        if (note?.content) {
          resetForm({ note: note.content });
        } else if (!note?.content && isOwnNote) {
          resetForm({ note: '' });
        }
        setShouldShowTextArea(isOwnNote);
      }
    }, [note?.content, open, isOwnNote, resetForm]);

    const handleClose = (
      shouldClearContent = false,
      shouldShowUnsavedWarning = false,
    ) => {
      if (form.formState.isDirty && shouldShowUnsavedWarning) {
        showUnsavedWarningModal();
        return;
      }
      if (shouldClearContent) {
        resetForm({ note: '' });
      }
      setShouldShowTextArea(false);
      closeUnsavedWarningModal();
      onClose();
    };

    const { mutate: saveNote, isLoading: isLoadingSaveNote } = useMutation(
      (values: Partial<NoteFormValues>) => {
        const payload = {
          jobId,
          applicationId,
          stageId,
          values,
          user: user || {},
        };

        if (note?.userId) {
          return updateApplicationStageNote(payload);
        }
        return createApplicationStageNote(payload);
      },
      {
        onSuccess: () => {
          enqueueSnackbar({
            title: note
              ? t('job_application.notes.edit.success')
              : t('job_application.notes.new.success'),
            variant: 'success',
          });
          queryClient.invalidateQueries(
            applicantsKeys.applicationDetail(jobId, applicationId),
          );
          handleClose(true, false);
        },
        onError: () => {
          enqueueSnackbar({
            title: t('general:error_title'),
            variant: 'error',
          });
        },
      },
    );

    const onSubmit = useCallback(
      (values: NoteFormValues) => {
        saveNote(values);
      },
      [saveNote],
    );

    const title = useMemo(() => {
      if (isOwnNote) {
        return note
          ? t('job_application.notes.edit.title')
          : t('job_application.notes.new.title');
      }
      return t('job_application.notes.created_by_long', {
        name: `${note?.userFirstName} ${note?.userLastName}`,
      });
    }, [note, isOwnNote, t]);

    const {
      modal: unsavedWarningModal,
      showModal: showUnsavedWarningModal,
      closeModal: closeUnsavedWarningModal,
    } = useUnsavedWarning(
      props => (
        <ModalUnsavedChanges
          {...props}
          onCloseWithoutSaving={() => {
            props.onConfirm();
            handleClose(true, false);
          }}
          onConfirm={() => {
            props.onConfirm();
            form.handleSubmit(onSubmit)();
          }}
          isLoading={isLoadingSaveNote}
        />
      ),
      !form.formState.isDirty,
    );

    return {
      children: (
        <Stack
          sx={{
            display: 'flex',
            flexDirection: 'column',
            gap: 1,
            height: '100%',
            minHeight: 0,
            width: '100%',
          }}
        >
          {note && !isOwnNote && (
            <Stack sx={{ gap: 1, width: '100%' }}>
              <HTMLBody body={note.content} />
            </Stack>
          )}
          <FormProvider {...form}>
            {isOwnNote && shouldShowTextArea && (
              <Stack
                sx={{
                  display: 'flex',
                  flex: 1,
                  minHeight: 0,
                }}
              >
                <FormTextArea
                  name="note"
                  textAreaProps={{
                    label: requiredLabel(
                      t('job_application.notes.description'),
                    ),
                    placeholder: t('general:write_something'),
                    sx: {
                      display: 'flex',
                      flexDirection: 'column',
                      flex: 1,
                      minHeight: 0,
                      // Subcontainer
                      '& > .MuiStack-root:last-of-type': {
                        flex: 1,
                        minHeight: 0,
                        overflow: 'hidden',
                        position: 'relative',
                      },
                      // toolbar
                      '& > .MuiStack-root > .MuiStack-root:first-of-type': {
                        flex: '0 0 auto',
                      },
                      // editable content
                      '& [contenteditable="true"]': {
                        bottom: 0,
                        left: 0,
                        overflowY: 'auto',
                        position: 'absolute',
                        right: 0,
                        top: 120,
                      },
                    },
                    helperText: t('job_application.notes.footer'),
                  }}
                />
              </Stack>
            )}
          </FormProvider>
          {unsavedWarningModal}
        </Stack>
      ),
      title,
      ...(isOwnNote && {
        primaryButtonProps: {
          children: note ? t('general:save_changes') : t('general:create'),
          onClick: form.handleSubmit(onSubmit),
          disabled:
            !form.formState.isValid ||
            !form.formState.isDirty ||
            isLoadingSaveNote,
          loading: isLoadingSaveNote,
        },
        secondaryButtonProps: {
          children: t('general:cancel'),
          onClick: () => handleClose(true, true),
        },
      }),
      size: isOwnNote ? 'large' : 'medium',
      onClose: () => handleClose(false, true),
    } as DrawerProps;
  };
