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

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

import { useDialogLayer } from '@material-hu/components/layers/Dialogs';
import {
  useDrawerLayer,
  useDrawerLayerItem,
} from '@material-hu/components/layers/Drawers';
import { type DrawerCloseReason } from '@material-hu/components/layers/Drawers/types';

import { useAuth } from 'src/contexts/JWTContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { type User } from 'src/types/user';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { getFormUsersList } from '../ResponsibleAutocomplete/utils';

import { RESPONSIBLE_DRAWER_ID } from './constants';
import { ResponsibleCard } from './ResponsibleCard';
import { ResponsibleDrawerBody } from './ResponsibleDrawer';
import { areUserSelectionsEqualById } from './userSelection';

export type ResponsiblePickerProps = {
  isNewGoal: boolean;
};

const toFormValue = (
  users: User[],
  isNewGoal: boolean,
): User | User[] | null => {
  if (users.length === 0) {
    return isNewGoal ? [] : null;
  }
  return isNewGoal ? users : users[0];
};

const NEEDS_CONFIRM_REASONS = new Set<DrawerCloseReason>([
  'backdropClick',
  'escapeKeyDown',
  'cancelButton',
  'dismissButton',
]);

export function ResponsiblePicker({ isNewGoal }: ResponsiblePickerProps) {
  const { t } = useLokaliseTranslation('goals');
  const { control, setValue } = useFormContext();
  const responsibleValue = useWatch({ control, name: 'responsible' });
  const { user: loggedUser } = useAuth();

  const HuGoThemeProvider = useHuGoTheme();

  const [draftUsers, setDraftUsers] = useState<User[]>([]);
  const [draftBaseline, setDraftBaseline] = useState<User[]>([]);
  const [searchInput, setSearchInput] = useState('');
  const debouncedSearch = useDeferredValue(searchInput);
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);

  const { openDialog, closeDialog } = useDialogLayer();
  const { closeDrawer: closeDrawerLayer } = useDrawerLayer();

  const hasDraftChanges = useMemo(
    () => !areUserSelectionsEqualById(draftUsers, draftBaseline),
    [draftUsers, draftBaseline],
  );

  const selectedUsers = useMemo(
    () => getFormUsersList(responsibleValue),
    [responsibleValue],
  );

  const userId = loggedUser?.id ?? 0;

  const applyDraftToForm = useCallback(() => {
    setValue('responsible', toFormValue(draftUsers, isNewGoal));
  }, [draftUsers, isNewGoal, setValue]);

  const finishCloseDrawer = useCallback(() => {
    setIsDrawerOpen(false);
    closeDrawerLayer(RESPONSIBLE_DRAWER_ID);
  }, [closeDrawerLayer]);

  const handleAttemptClose = useCallback(
    (reason?: DrawerCloseReason) => {
      const needsConfirm =
        hasDraftChanges && !!reason && NEEDS_CONFIRM_REASONS.has(reason);

      if (needsConfirm) {
        openDialog({
          title: t('new.responsible_unsaved_title'),
          textBody: t('new.responsible_unsaved_description'),
          onClose: () => closeDialog(),
          primaryButtonProps: {
            children: t('general:apply'),
            onClick: (e: MouseEvent) => {
              e.stopPropagation();
              applyDraftToForm();
              finishCloseDrawer();
              closeDialog();
            },
          },
          secondaryButtonProps: {
            children: t('general:discard'),
            onClick: (e: MouseEvent) => {
              e.stopPropagation();
              finishCloseDrawer();
              closeDialog();
            },
          },
          dialogProps: { fullWidth: true, maxWidth: 'sm' },
        });
        return;
      }
      finishCloseDrawer();
    },
    [
      applyDraftToForm,
      closeDialog,
      finishCloseDrawer,
      hasDraftChanges,
      openDialog,
      t,
    ],
  );

  const { openDrawer } = useDrawerLayerItem(RESPONSIBLE_DRAWER_ID, {
    title: t('new.responsibles'),
    hasBackButton: false,
    onClose: handleAttemptClose,
    children: (
      <ResponsibleDrawerBody
        userId={userId}
        debouncedSearch={debouncedSearch}
        isDrawerOpen={isDrawerOpen}
        isNewGoal={isNewGoal}
        loggedUser={loggedUser ?? null}
        draftUsers={draftUsers}
        setDraftUsers={setDraftUsers}
        searchInput={searchInput}
        onSearchInputChange={setSearchInput}
      />
    ),
    primaryButtonProps: {
      fullWidth: true,
      disabled: draftUsers.length === 0,
      children: t('general:apply'),
      onClick: () => {
        applyDraftToForm();
        finishCloseDrawer();
      },
    },
    secondaryButtonProps: {
      fullWidth: true,
      children: t('general:cancel'),
      onClick: () => {
        handleAttemptClose('cancelButton');
      },
    },
  });

  const handleOpen = useCallback(() => {
    if (!loggedUser) return;
    const initial = getFormUsersList(responsibleValue);
    setDraftBaseline(initial);
    setDraftUsers(initial);
    setSearchInput('');
    setIsDrawerOpen(true);
    openDrawer();
  }, [loggedUser, openDrawer, responsibleValue]);

  const disabled = !isNewGoal;

  return (
    <HuGoThemeProvider>
      <Stack sx={{ gap: 1.5 }}>
        <ResponsibleCard
          label={t('new.responsibles')}
          title={t('new.responsible_card_title')}
          description={t('new.responsible_card_description')}
          tooltipLabel={t('new.responsible_scope_tooltip', {
            count: selectedUsers.length,
          })}
          selectedUsers={selectedUsers}
          onOpen={handleOpen}
          disabled={disabled}
        />
      </Stack>
    </HuGoThemeProvider>
  );
}

export default ResponsiblePicker;
