import { useId, useRef, useState } from 'react';
import { useMutation } from 'react-query';

import { type AxiosError } from 'axios';

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

import { queryClient } from 'src/config/react-query';
import {
  assignAgentToMultipleTasks,
  assignAgentToTask,
} from 'src/pages/dashboard/serviceManagement/services';
import {
  type Task,
  type UserTask,
} from 'src/pages/dashboard/serviceManagement/types';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { getFullName } from 'src/utils/userUtils';

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

import { useMultipleAssignmentConfirmModal } from './modals/useMultipleAssignmentConfirmModal';
import { useSingleAssignmentConfirmModal } from './modals/useSingleAssignmentConfirmModal';
import useSnackbar from './useSnackbar';

const useAgentReassignment = <T extends Task>(params?: unknown) => {
  const id = useId();
  const { t } = useLokaliseTranslation('service_management');
  const { showSnackbar } = useSnackbar();

  const [selectedAgent, setSelectedAgent] = useState<UserTask | null>(null);

  // Single Task Assignment
  const [selectedTask, setSelectedTask] = useState<T | null>(null);
  const [singleAssignmentAnchorEl, setSingleAssignmentAnchorEl] =
    useState<HTMLElement | null>(null);
  const singleAssignmentMenuOpen = Boolean(singleAssignmentAnchorEl);
  const singleAssignmentMenuId = singleAssignmentMenuOpen ? id : undefined;

  // Multiple Task Assignment
  const [selectedTasks, setSelectedTasks] = useState<T[]>([]);
  const [multipleAssignmentAnchorEl, setMultipleAssignmentAnchorEl] =
    useState<HTMLElement | null>(null);
  const multipleAssignmentMenuOpen = Boolean(multipleAssignmentAnchorEl);
  const multipleAssignmentMenuId = multipleAssignmentMenuOpen
    ? `${id}-multiple`
    : undefined;

  const handleOpenMultipleAssignmentMenu = (
    event: React.MouseEvent<HTMLElement>,
  ) => {
    setMultipleAssignmentAnchorEl(event.currentTarget);
  };

  const handleCloseMultipleAssignmenMenu = () => {
    setMultipleAssignmentAnchorEl(null);
  };

  const handleCloseSingleAssignmentMenu = () => {
    setSingleAssignmentAnchorEl(null);
  };

  const selectedAgentFullName = selectedAgent ? getFullName(selectedAgent) : '';
  const currentAgentFullName = selectedTask?.assignee
    ? getFullName(selectedTask.assignee)
    : '';

  const invalidateTaskQueries = () => {
    if (selectedTask) {
      queryClient.invalidateQueries(
        serviceManagementKeys.tasks.detail(selectedTask.id),
      );
      queryClient.invalidateQueries(
        serviceManagementKeys.activities.list(selectedTask.id),
      );
    }
    if (params) {
      queryClient.invalidateQueries(
        serviceManagementKeys.tasks.hydratedList(params),
      );
      queryClient.invalidateQueries(serviceManagementKeys.tasks.list(params));
    }
  };

  // Refs to break the circular dependency between mutations and modal close functions
  // (mutations need closeModal in onSettled, modal hooks need isLoading from mutations)
  const closeSingleModalRef = useRef<() => void>(() => {
    /* noop */
  });
  const closeMultipleModalRef = useRef<() => void>(() => {
    /* noop */
  });

  const singleAssigmentMutation = useMutation(
    () => assignAgentToTask(selectedTask?.id ?? '', selectedAgent?.id ?? 0),
    {
      onSuccess: () => {
        showSnackbar({
          title: t('single_assignment_success', {
            agentName: selectedAgentFullName,
          }),
          variant: 'success',
        });
        invalidateTaskQueries();
      },
      onError: (error: AxiosError<{ code: string }>) => {
        const errorCode = error?.response?.data?.code;
        if (errorCode === 'AGENT_MATCHES_INITIATOR') {
          showSnackbar({
            title: t('single_assignment_error_requester'),
            variant: 'error',
          });
        } else {
          showSnackbar({
            title: t('single_assignment_error', {
              agentName: selectedAgentFullName,
            }),
            variant: 'error',
          });
        }
      },
      onSettled: () => {
        closeSingleModalRef.current();
        handleCloseSingleAssignmentMenu();
      },
    },
  );

  const multipleAssignmentMutation = useMutation(
    () =>
      assignAgentToMultipleTasks(
        selectedTasks.map(task => task.id),
        selectedAgent?.id ?? 0,
      ),
    {
      onSuccess: async () => {
        showSnackbar({
          title: t('multiple_assignment_success', {
            count: selectedTasks.length,
            agentName: selectedAgentFullName,
          }),
          variant: 'success',
        });
        invalidateTaskQueries();
      },
      onError: () => {
        showSnackbar({
          title: t('multiple_assignment_error', {
            count: selectedTasks.length,
            agentName: selectedAgentFullName,
          }),
          variant: 'error',
        });
      },
      onSettled: (_, error) => {
        handleCloseMultipleAssignmenMenu();
        closeMultipleModalRef.current();
        setSelectedAgent(null);
        if (!error) {
          setSelectedTasks([]);
        }
      },
    },
  );

  const handleConfirmSingleAssignment = () => {
    singleAssigmentMutation.mutate();
  };

  const handleConfirmMultipleAssignment = () => {
    if (selectedAgent) {
      multipleAssignmentMutation.mutate();
    }
  };

  // Uses closeMultipleModalRef so it can be defined before the modal hook resolves
  const handleCloseAssignmentConfirmation = () => {
    closeMultipleModalRef.current();
    handleCloseMultipleAssignmenMenu();
    setSelectedAgent(null);
  };

  // Handlers that reference open functions (called lazily — defined before modal hooks is safe)
  const handleMultipleAssignment = (agent: UserTask) => {
    setSelectedAgent(agent);
    openMultipleAssignmentConfirmationModal();
  };

  const handleSingleAssignment = (agent: UserTask) => {
    setSelectedAgent(agent);
    openSingleAssignmentConfirmationModal();
  };

  const handleOpenSingleAssignmentMenu = (el: HTMLElement | null, task: T) => {
    if (!el) return;
    if (singleAssignmentAnchorEl) {
      handleCloseSingleAssignmentMenu();
      return;
    }
    setSingleAssignmentAnchorEl(el);
    setSelectedTask(task);
  };

  const {
    singleAssignmentConfirmationModal,
    openSingleAssignmentConfirmationModal,
    closeSingleAssignmentConfirmationModal,
  } = useSingleAssignmentConfirmModal({
    selectedAgentFullName,
    currentAgentFullName,
    hasCurrentAssignee: Boolean(selectedTask?.assignee),
    onConfirm: handleConfirmSingleAssignment,
    onDismiss: () => setSelectedAgent(null),
    isLoading: singleAssigmentMutation.isLoading,
  });

  const {
    multipleAssignmentConfirmationModal,
    openMultipleAssignmentConfirmationModal,
    closeMultipleAssignmentConfirmationModal,
  } = useMultipleAssignmentConfirmModal({
    count: selectedTasks.length,
    selectedAgentFullName,
    onConfirm: handleConfirmMultipleAssignment,
    onClose: handleCloseAssignmentConfirmation,
    isLoading: multipleAssignmentMutation.isLoading,
  });

  // Keep refs in sync after each render
  closeSingleModalRef.current = closeSingleAssignmentConfirmationModal;
  closeMultipleModalRef.current = closeMultipleAssignmentConfirmationModal;

  const SingleAssignmentPopoverComponent = (
    <HuMenu
      id={singleAssignmentMenuId}
      anchorEl={singleAssignmentAnchorEl}
      open={singleAssignmentMenuOpen}
      onClose={handleCloseSingleAssignmentMenu}
      position="left"
      sx={{ minWidth: '300px', zIndex: 1000 }}
    >
      <CandidateAgentAutocomplete
        onSelect={handleSingleAssignment}
        serviceItemId={selectedTask?.catalogItem.id ?? ''}
        currentAssignedAgent={selectedTask?.assignee}
      />
    </HuMenu>
  );

  const MultipleAssignmentPopoverComponent = (
    <HuMenu
      id={multipleAssignmentMenuId}
      anchorEl={multipleAssignmentAnchorEl}
      open={multipleAssignmentMenuOpen}
      onClose={handleCloseMultipleAssignmenMenu}
      position="left"
      sx={{ zIndex: 1000, minWidth: '320px' }}
    >
      <CandidateAgentAutocomplete
        onSelect={handleMultipleAssignment}
        serviceItemId={selectedTasks[0]?.catalogItem?.id ?? ''}
        currentAssignedAgent={selectedTask?.assignee}
      />
    </HuMenu>
  );

  return {
    selectedAgent,
    setSelectedAgent,
    selectedTask,
    selectedTasks,
    setSelectedTasks,
    // Single Assignment
    singleAssignmentConfirmationModal,
    openSingleAssignmentConfirmationModal,
    closeSingleAssignmentConfirmationModal,
    handleOpenSingleAssignmentMenu,
    handleCloseSingleAssignmentMenu,
    handleSelectAgent: handleSingleAssignment,
    // Multiple Assignment
    multipleAssignmentConfirmationModal,
    openMultipleAssignmentConfirmationModal,
    closeMultipleAssignmentConfirmationModal,
    handleOpenMultipleAssignmentMenu,
    handleCloseMultipleAssignmenMenu,
    handleMultipleAssignment,
    // Popover components
    SingleAssignmentPopoverComponent,
    MultipleAssignmentPopoverComponent,
  };
};

export default useAgentReassignment;
