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

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

import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { queryClient } from 'src/config/react-query';
import useGeneralError from 'src/hooks/useGeneralError';
import { usersKeys } from 'src/pages/dashboard/Users/queries';
import {
  getPoliciesDefaultApprovers,
  modifyPoliciesDefaultApprovers,
  type PolicyApprovalStepsParams,
} from 'src/services/timeTrackingService';
import { getPublicUsers } from 'src/services/usersService';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { FormApprovalStepsList } from 'src/components/ApprovalStepsList/form';
import { ApprovalWorkflow } from 'src/components/ApprovalStepsList/types';

import { timeTrackingKeys } from '../../queries';

import {
  type ApproversFormFields,
  approversFields,
  INITIAL_VALUES,
} from './form';
import {
  formatApprovalStepsForPoliciesApi,
  mapPolicyStepToApprovalStep,
  mapUsersToApprovalStepUsers,
} from './utils';

type ApprovalStepsMutationPayload = {
  params: PolicyApprovalStepsParams;
  action: 'create' | 'edit' | 'delete';
};

const successKeys: Record<ApprovalStepsMutationPayload['action'], string> = {
  create: 'approval_requests:step_configuration.actions.step_create_success',
  edit: 'approval_requests:step_configuration.actions.step_edit_success',
  delete: 'approval_requests:step_configuration.actions.step_delete_success',
};

const Approvers = () => {
  const { t } = useLokaliseTranslation(['time_tracker', 'approval_requests']);
  const { enqueueSnackbar } = useHuSnackbar();
  const showGeneralError = useGeneralError();

  const { data, isLoading } = useQuery(
    timeTrackingKeys.policiesDefaultApprovers(),
    getPoliciesDefaultApprovers,
    {
      select: response => ({
        approvalUsers:
          response.data.steps.length > 0
            ? response.data.steps.map(mapPolicyStepToApprovalStep)
            : INITIAL_VALUES.approvalUsers,
        approvalWorkflow: ApprovalWorkflow.DEFAULT,
      }),
    },
  );

  const form = useForm<ApproversFormFields>({
    defaultValues: INITIAL_VALUES,
    mode: 'onChange',
    values: data,
  });

  const approvalUsers = useWatch({
    control: form.control,
    name: approversFields.approval.approvalUsers,
  });

  const modifyApprovalStepsMutation = useMutation(
    ({ params }: ApprovalStepsMutationPayload) =>
      modifyPoliciesDefaultApprovers(params),
    {
      onSuccess: (response, { action }) => {
        queryClient.setQueryData(timeTrackingKeys.policiesDefaultApprovers(), {
          data: { steps: response.data.steps },
        });
        enqueueSnackbar({
          title: t(successKeys[action]),
          variant: 'success',
        });
      },
      onError: error => {
        showGeneralError(
          error,
          t('approval_requests:step_configuration.actions.error'),
          t('approval_requests:step_configuration.actions.error_description'),
        );
      },
    },
  );

  const handleRemoveStep = (removedIndex: number) => {
    const newApprovalUsers = approvalUsers.filter(
      (_, index) => index !== removedIndex,
    );
    const payload = formatApprovalStepsForPoliciesApi(newApprovalUsers);
    modifyApprovalStepsMutation.mutate({ params: payload, action: 'delete' });
  };

  return (
    <Stack sx={{ width: '100%' }}>
      <FormProvider {...form}>
        <FormApprovalStepsList
          name={approversFields.approval.approvalUsers}
          isLoadingSteps={isLoading}
          approvalStepDrawerProps={{
            onSave: (updatedApprovalUsers, action) => {
              modifyApprovalStepsMutation.mutate({
                params: formatApprovalStepsForPoliciesApi(updatedApprovalUsers),
                action: action ?? 'edit',
              });
            },
            usersService: {
              getUsers: getPublicUsers,
              queryKey: usersParams => usersKeys.usersWithParams(usersParams),
              getNextPageParam: lastPage =>
                lastPage.data.page < lastPage.data.totalPages
                  ? lastPage.data.page
                  : undefined,
            },
            usersMapping: mapUsersToApprovalStepUsers,
          }}
          cardProps={{
            menuProps: {
              onRemoveStep: handleRemoveStep,
            },
          }}
        />
      </FormProvider>
    </Stack>
  );
};

export default Approvers;
