import { useEffect, useRef, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation } from 'react-query';

import { IconCheck, IconPlaystationX } from '@material-hu/icons/tabler';
import Divider from '@material-hu/mui/Divider';
import Stack from '@material-hu/mui/Stack';

import Button from '@material-hu/components/design-system/Buttons/Button';
import HuFormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import HuMenu from '@material-hu/components/design-system/Menu';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/logging';
import { useAuth } from 'src/contexts/JWTContext';
import { getApprovalStateName } from 'src/pages/dashboard/serviceManagement/utils';
import { updateState } from 'src/pages/dashboard/serviceManagement/services';
import {
  ApprovalScreenSource,
  ApprovalStateName,
  ServiceManagementRole,
  type StateTransition,
  type Task,
} from 'src/pages/dashboard/serviceManagement/types';
import { EventName } from 'src/types/amplitude';
import { useLokaliseTranslation } from 'src/utils/i18n';

let currentOpenMenu: (() => void) | null = null;

type ApprovalActionsProps = {
  task: Pick<Task, 'id' | 'catalogItem' | 'name' | 'state' | 'formAnswerId'>;
  states: StateTransition[];
  invalidateQueries?: () => void;
  screenSource?: ApprovalScreenSource;
};

type FormData = {
  message: string;
};

export const ApprovalActions = ({
  task,
  states,
  invalidateQueries,
  screenSource,
}: ApprovalActionsProps) => {
  const { t } = useLokaliseTranslation(['service_management', 'general']);
  const { enqueueSnackbar } = useHuSnackbar();
  const { user } = useAuth();
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
  const [approvalType, setApprovalType] = useState<ApprovalStateName | null>(
    null,
  );
  const closeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const form = useForm<FormData>({
    defaultValues: { message: '' },
    mode: 'onChange',
  });

  const bottomSpacing =
    screenSource === ApprovalScreenSource.APPROVAL_DETAIL ? 110 : 0;

  const isReject = approvalType === ApprovalStateName.REJECTED;

  const { mutate: update, isLoading } = useMutation(
    (body: { stateId?: string; message?: string }) =>
      updateState(task!.id, body),
    {
      onSuccess: async () => {
        await invalidateQueries?.();

        logEvent(EventName.SERVICE_MGMT_APPROVAL_ACTION_TAKEN, {
          serviceId: task?.catalogItem?.id,
          serviceName: task?.catalogItem?.name,
          approval_step_id: task?.id,
          approval_action_type: approvalType,
          approver_role: user?.isAgent
            ? ServiceManagementRole.AGENT
            : ServiceManagementRole.APPROVER,
          screen_source: screenSource,
        });
        handleClose();
        enqueueSnackbar({
          title: t(
            `approvals.${isReject ? 'reject_success' : 'approval_success'}`,
            { name: task?.name },
          ),
          variant: 'success',
          spacing: {
            bottom: bottomSpacing,
          },
        });
      },
      onError: () => {
        handleClose();
        enqueueSnackbar({
          title: t(
            `approvals.${isReject ? 'reject_error' : 'approval_error'}`,
            { name: task?.name },
          ),
          description: t('try_again_later'),
          variant: 'error',
          spacing: {
            bottom: bottomSpacing,
          },
        });
      },
    },
  );

  const handleApproval = (stateName: ApprovalStateName, message?: string) => {
    const trimmedMessage = message?.trim();
    const body = {
      stateId: states?.find(
        state => getApprovalStateName(state.stateName) === stateName,
      )?.stateId,
      ...(trimmedMessage && { message: trimmedMessage }),
    };
    update(body);
  };

  const handleButtonClick = (
    event: React.MouseEvent<HTMLElement>,
    type: ApprovalStateName,
  ) => {
    event.stopPropagation();
    currentOpenMenu?.();
    if (closeTimeoutRef.current) {
      clearTimeout(closeTimeoutRef.current);
      closeTimeoutRef.current = null;
    }
    setAnchorEl(event.currentTarget);
    setApprovalType(type);
    currentOpenMenu = handleClose;
  };

  const handleClose = () => {
    setAnchorEl(null);
    form.reset();
    if (closeTimeoutRef.current) {
      clearTimeout(closeTimeoutRef.current);
    }
    closeTimeoutRef.current = setTimeout(() => {
      currentOpenMenu = null;
      setApprovalType(null);
      closeTimeoutRef.current = null;
    }, 500);
  };

  useEffect(() => {
    return () => {
      if (closeTimeoutRef.current) {
        clearTimeout(closeTimeoutRef.current);
      }
    };
  }, []);

  const message = form.watch('message');

  const handleConfirmClick = (event: React.MouseEvent) => {
    event.stopPropagation();

    if (isReject && !message?.trim()) {
      form.setError('message', {
        type: 'onChange',
        message: t('general:required_field'),
      });
      return;
    }

    if (approvalType) {
      handleApproval(approvalType, message);
    }
  };

  return (
    <>
      <Stack sx={{ flexDirection: 'row', gap: 1 }}>
        <Button
          variant="secondary"
          startIcon={<IconPlaystationX />}
          sx={{ width: '140px' }}
          onClick={e => handleButtonClick(e, ApprovalStateName.REJECTED)}
          onMouseDown={e => e.stopPropagation()}
        >
          {t('approvals.reject')}
        </Button>
        <Button
          variant="primary"
          startIcon={<IconCheck />}
          sx={{ width: '140px' }}
          onClick={e => handleButtonClick(e, ApprovalStateName.APPROVED)}
          onMouseDown={e => e.stopPropagation()}
        >
          {t('approvals.approve')}
        </Button>
      </Stack>

      <HuMenu
        anchorEl={anchorEl}
        open={Boolean(anchorEl)}
        onClose={handleClose}
        position="right"
        sx={{
          '& .MuiPaper-root': {
            width: '390px',
            minWidth: '390px',
          },
          '& .MuiList-root': {
            maxWidth: '390px',
          },
        }}
      >
        <FormProvider {...form}>
          <Stack
            sx={{ gap: 2, p: 2 }}
            onClick={e => e.stopPropagation()}
            onMouseDown={e => e.stopPropagation()}
          >
            <HuFormInputClassic
              name="message"
              inputProps={{
                placeholder: t('text_placeholder'),
                label: t('approvals.message'),
                multiline: true,
                minRows: 6,
                maxRows: 6,
                maxLength: 500,
                hasCounter: false,
                fullWidth: true,
                onFocus: (e: React.FocusEvent) => e.stopPropagation(),
                onKeyDown: () => form.clearErrors('message'),
              }}
            />
          </Stack>
          <Divider />
          <Stack
            sx={{ flexDirection: 'row', gap: 1, p: 2 }}
            onClick={e => e.stopPropagation()}
            onMouseDown={e => e.stopPropagation()}
          >
            <Button
              variant="secondary"
              onClick={handleClose}
              size="small"
              fullWidth
            >
              {t('general:cancel')}
            </Button>
            <Button
              size="small"
              variant="primary"
              onClick={handleConfirmClick}
              loading={isLoading}
              fullWidth
            >
              {isReject ? t('approvals.reject') : t('approvals.approve')}
            </Button>
          </Stack>
        </FormProvider>
      </HuMenu>
    </>
  );
};
