import { useMutation, useQuery } from 'react-query';

import { useModal } from '@material-hu/hooks/useModal';

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

import { logEvent } from 'src/config/logging';
import { queryClient } from 'src/config/react-query';
import { useAuth } from 'src/contexts/JWTContext';
import {
  getStateName,
  isTerminal,
  ServiceManagementTaskStateName,
} from 'src/pages/dashboard/serviceManagement/utils';
import {
  getApprovalGroupsCount,
  getTasksCount,
  getTransitionsStates,
  updateState,
} from 'src/pages/dashboard/serviceManagement/services';
import {
  ApprovalStateName,
  ServiceManagementRole,
  type StateTransition,
  type Task,
} from 'src/pages/dashboard/serviceManagement/types';
import { EventName } from 'src/types/amplitude';
import { useLokaliseTranslation } from 'src/utils/i18n';

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

type UseStateTransitionParams = {
  taskData?: Task;
  isAgentSide: boolean;
};

export const useStateTransition = ({
  taskData,
  isAgentSide,
}: UseStateTransitionParams) => {
  const { t } = useLokaliseTranslation('service_management');
  const { user: loggedUser } = useAuth();

  const { data: states, isLoading: isLoadingStates } = useQuery(
    serviceManagementKeys.states.list(taskData?.state.id ?? ''),
    () => getTransitionsStates(taskData?.state.id ?? ''),
    {
      enabled: !!taskData,
      select: response => response.data,
    },
  );

  const { refetch, isRefetching: approvalsCountLoading } = useQuery(
    serviceManagementKeys.approvalGroups.count(taskData?.id ?? '', [
      ApprovalStateName.PENDING,
    ]),
    () =>
      getApprovalGroupsCount(taskData?.id ?? '', [ApprovalStateName.PENDING]),
    { enabled: false },
  );

  const { refetch: refetchTasksCount, isRefetching: tasksCountLoading } =
    useQuery(
      serviceManagementKeys.tasks.childrenCount(taskData?.id ?? '', false),
      () => getTasksCount(taskData?.id ?? '', false),
      { enabled: false },
    );

  const { mutate: update, isLoading: isLoadingUpdate } = useMutation(
    (body: { stateId?: string }) => updateState(taskData?.id ?? '', body),
    {
      onSuccess: response => {
        queryClient.invalidateQueries(
          serviceManagementKeys.tasks.detail(taskData?.id ?? ''),
        );
        queryClient.invalidateQueries(
          serviceManagementKeys.activities.list(taskData?.id ?? ''),
        );
        queryClient.invalidateQueries([
          ...serviceManagementKeys.approvalGroups.all(),
          taskData?.id,
        ]);

        logEvent(EventName.SERVICE_MGMT_STATE_CHANGED, {
          role: isAgentSide
            ? ServiceManagementRole.AGENT
            : ServiceManagementRole.INITIATOR,
          serviceId: taskData?.catalogItem?.id,
          serviceName: taskData?.catalogItem?.name,
          requestId: taskData?.id,
          formId: taskData?.formAnswerId,
          stateName: getStateName(taskData?.state.name ?? ''),
          status: getStateName(response?.data?.state?.name ?? ''),
        });
      },
    },
  );

  const {
    modal: terminalSureModal,
    showModal: showTerminalSureModal,
    closeModal: closeFormModal,
  } = useModal(
    ({
      newState,
      descriptionKey,
    }: {
      newState: StateTransition;
      descriptionKey: string;
    }) => (
      <Dialog
        title={t('terminal_change.title')}
        textBody={t(descriptionKey)}
        onClose={closeFormModal}
        primaryButtonProps={{
          variant: 'primary',
          children: t('continue'),
          onClick: () => {
            update({ stateId: newState.stateId });
            closeFormModal();
          },
        }}
        secondaryButtonProps={{
          variant: 'tertiary',
          children: t('general:cancel'),
          onClick: closeFormModal,
        }}
      />
    ),
    { maxWidth: 'sm' },
  );

  const handleUpdateState = async (newState: StateTransition) => {
    if (isTerminal(newState)) {
      try {
        const { data } = await refetch({ throwOnError: true });
        const approvalsCount = data?.data?.count ?? 0;
        const { data: tasksCountData } = await refetchTasksCount({
          throwOnError: true,
        });
        const tasksCount = tasksCountData?.data?.count ?? 0;

        const descriptionKey = () => {
          if (approvalsCount > 0 && tasksCount > 0)
            return 'terminal_change.approvals_and_tasks';
          return approvalsCount > 0
            ? 'terminal_change.approvals'
            : 'terminal_change.tasks';
        };

        if (approvalsCount > 0 || tasksCount > 0) {
          showTerminalSureModal({ newState, descriptionKey: descriptionKey() });
        } else {
          update({ stateId: newState.stateId });
        }
      } catch (_error) {
        // noop
      }
    } else {
      update({ stateId: newState.stateId });
    }
  };

  const handleAssignMe = () => {
    const nextState = states?.find(
      state =>
        getStateName(state.stateName) ===
        ServiceManagementTaskStateName.ASSIGNED,
    );
    update({ stateId: nextState?.stateId });
  };

  const stateName = getStateName(taskData?.state?.name ?? '');
  const isOwnerAgent = taskData?.assignee?.id === loggedUser?.id;

  const showStateTransitions =
    isAgentSide &&
    isOwnerAgent &&
    !!states &&
    states.length > 0 &&
    (stateName !== ServiceManagementTaskStateName.UNASSIGNED ||
      isLoadingUpdate);

  const showAssignMe =
    isAgentSide &&
    !!taskData?.isAssignableAgent &&
    stateName === ServiceManagementTaskStateName.UNASSIGNED &&
    loggedUser?.id !== taskData?.initiator?.id;

  const showStateLoading =
    isLoadingUpdate ||
    isLoadingStates ||
    approvalsCountLoading ||
    tasksCountLoading;

  return {
    states,
    isLoadingStates,
    isLoadingUpdate,
    showStateLoading,
    showStateTransitions,
    showAssignMe,
    stateName,
    terminalSureModal,
    handleUpdateState,
    handleAssignMe,
    update,
  };
};
