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

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

import UserAvatar from '@material-hu/components/composed-components/UserAvatar';
import CardContainer from '@material-hu/components/design-system/CardContainer';
import Drawer from '@material-hu/components/design-system/Drawer';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import useGeneralError from 'src/hooks/useGeneralError';
import DescriptionInput from 'src/pages/dashboard/timeOff/components/inputs/DescriptionInput';
import { updateBalanceReport } from 'src/pages/dashboard/timeOff/queries';
import { adjustAvailableTime } from 'src/services/vacations';
import {
  type AdjustAvailableTimeForm,
  AllowanceType,
  type BalanceReport,
  type OperationsBalance,
} from 'src/types/vacations';
import { useLokaliseTranslation } from 'src/utils/i18n';

import AdjustBalanceFooter from './AdjustBalanceFooter';
import AdjustBalanceCycle from './inputs/AdjustBalanceCycle';
import AdjustBalanceTypeInput from './inputs/AdjustBalanceTypeInput';

export type AdjustBalanceProps = {
  open: boolean;
  onClose: () => void;
  reportItem: BalanceReport;
};

export type AdjustBalanceForm = {
  operation: OperationsBalance;
  amount: number;
  observations: string;
  cycleId: number;
};

export const AdjustBalance = (props: AdjustBalanceProps) => {
  const { open, onClose, reportItem } = props;

  const { t } = useLokaliseTranslation('time_off');

  const form = useForm<AdjustBalanceForm>({
    defaultValues: {
      operation: undefined,
      amount: undefined,
      observations: undefined,
      cycleId: undefined,
    },
    mode: 'onChange',
  });

  const {
    handleSubmit,
    reset,
    formState: { isSubmitting },
  } = form;

  const { watch } = form;

  const operationValue = watch('operation');
  const amountValue = watch('amount');

  const showGeneralError = useGeneralError();
  const { enqueueSnackbar } = useHuSnackbar();

  const { mutate, isLoading } = useMutation(
    ({ operation, amount, observations, cycleId }: AdjustAvailableTimeForm) =>
      adjustAvailableTime({
        policyTypeId: reportItem.policy.policyType.id,
        userId: reportItem.user?.id,
        operation,
        amount,
        observations,
        cycleId,
      }),
    {
      onSuccess: () => {
        updateBalanceReport();
        handleCloseModal();
        enqueueSnackbar({
          title: t('ADJUSTMENT_APPLIED_SUCCESSFULLY'),
          variant: 'success',
        });
      },
      onError: (err: any) => {
        showGeneralError(err, t('ERROR_UPDATE_BALANCE'));
      },
    },
  );

  const handleCloseModal = () => {
    reset();
    onClose();
  };

  const submit = (values: AdjustBalanceForm) => {
    const formattedValues = {
      ...values,
      amount: Number(values.amount),
    };
    mutate(formattedValues);
  };

  const adjustTypeInputs = [
    {
      id: 'type_request',
      option: (
        <AdjustBalanceTypeInput
          namesInput={['operation', 'amount']}
          reportItem={reportItem}
        />
      ),
    },
    {
      id: 'cycle',
      option: (
        <AdjustBalanceCycle
          name="cycleId"
          reportItem={reportItem}
        />
      ),
    },
    {
      id: 'observations',
      option: <DescriptionInput name="observations" />,
    },
  ];

  return (
    <FormProvider {...form}>
      <Drawer
        open={open}
        onClose={handleCloseModal}
        title={
          reportItem.policy.allowanceType === AllowanceType.BASIC_ANNUAL
            ? t('time_available_adjustment')
            : t('time_used_adjustment')
        }
        primaryButtonProps={{
          children: t('APPLY'),
          onClick: handleSubmit(submit),
          loading: isLoading || isSubmitting,
          disabled: isLoading || isSubmitting,
        }}
        footer={
          operationValue && amountValue && !isNaN(Number(amountValue)) ? (
            <AdjustBalanceFooter reportItem={reportItem} />
          ) : null
        }
      >
        <Stack sx={{ gap: 2 }}>
          <CardContainer
            color="grey"
            fullWidth
          >
            <Stack>
              <Typography variant="globalXXS">{t('employee')}</Typography>
              <UserAvatar
                user={reportItem.user}
                sx={{
                  '& .MuiListItem-root': {
                    p: 0,
                  },
                }}
              />
            </Stack>
          </CardContainer>

          <CardContainer
            color="grey"
            fullWidth
          >
            <Stack>
              <Typography variant="globalXXS">
                {t('policy_type_one')}
              </Typography>
              <Typography
                variant="globalS"
                sx={{
                  fontWeight: 'fontWeightSemiBold',
                }}
              >
                {reportItem?.policy.policyType.name}
              </Typography>
            </Stack>
          </CardContainer>

          <CardContainer
            color="grey"
            fullWidth
          >
            <Stack>
              <Typography variant="globalXXS">{t('policy')}</Typography>
              <Typography
                variant="globalS"
                sx={{
                  fontWeight: 'fontWeightSemiBold',
                }}
              >
                {reportItem?.policy?.name}
              </Typography>
            </Stack>
          </CardContainer>
          <Stack sx={{ gap: 2 }}>
            {adjustTypeInputs.map(({ id, option }) => (
              <Fragment key={id}>{option}</Fragment>
            ))}
          </Stack>
        </Stack>
      </Drawer>
    </FormProvider>
  );
};

export default AdjustBalance;
