import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useQuery } from 'react-query';
import { useNavigate, useParams } from 'react-router';

import { zodResolver } from '@hookform/resolvers/zod';
import { type TFunction } from 'i18next';
import { isEqual } from 'lodash-es';

import { logEvent } from 'src/config/logging';
import { EVENTS_SOCKETS } from 'src/constants/sockets';
import { useAuth } from 'src/contexts/JWTContext';
import { useSocket } from 'src/contexts/SocketContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import useLocalStorage from 'src/hooks/useLocalStorage';
import { serviceManagementKeys } from 'src/pages/dashboard/serviceManagement/queries';
import { serviceManagementRoutes } from 'src/pages/dashboard/serviceManagement/routes';
import { normalizeViewFilters } from 'src/pages/dashboard/serviceManagement/utils';
import { getTasks } from 'src/pages/dashboard/serviceManagement/services';
import {
  type FilterFormValues,
  PlatformType,
  ServiceManagementRole,
  type Task,
  TasksType,
  type View,
} from 'src/pages/dashboard/serviceManagement/types';
import { EventName } from 'src/types/amplitude';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { hasAllPermissions, UserPermissions } from 'src/utils/permissions';
import { isMobile } from 'src/utils/recognitions';

import { useModuleConfiguration } from '../../contexts/ModuleConfigurationContext';
import useAgentReassignment from '../../hooks/useAgentReassignment';
import useServiceItemSearchParams from '../../hooks/useServiceItemSearchParams';
import useTaskCommentsUpdater from '../../hooks/useTaskCommentsUpdater';
import useTaskStateListUpdater from '../../hooks/useTaskStateListUpdater';
import useViews from '../../hooks/useViews';
import { useConfirmSaveViewModal } from '../components/modals/useConfirmSaveViewModal';
import { FILTERS_DEFAULT_VALUES } from '../constants';
import { createCoordinatorFiltersSchema } from '../form/schemas';
import { getFilterParams } from '../utils';

import useViewInputNameModal from './useViewInputNameModal';

export const useTicketViews = () => {
  const { t } = useLokaliseTranslation('service_management');
  const HugoThemeProvider = useHuGoTheme();
  const navigate = useNavigate();
  const socket = useSocket();
  const { permissions } = useAuth();

  const canDownloadTaskReport = useMemo(
    () =>
      hasAllPermissions(permissions, [
        UserPermissions.SERVICE_MANAGER_AGENT_REPORTS,
      ]),
    [permissions],
  );

  const [isSidebarCollapsed, setIsSidebarCollapsed] = useLocalStorage(
    'sm_viewSidebar_collapsed',
    false,
  );
  const [filterDrawerOpen, setFilterDrawerOpen] = useState(false);
  const [appliedFilters, setAppliedFilters] = useState<FilterFormValues | null>(
    null,
  );
  const [stableSelectedViewHasNewFilters, setStableSelectedViewHasNewFilters] =
    useState(false);
  const [downloadReportDrawerOpen, setDownloadReportDrawerOpen] =
    useState(false);

  const alertRef = useRef<{ closeMenu: () => void }>(null);

  const form = useForm<FilterFormValues>({
    defaultValues: FILTERS_DEFAULT_VALUES,
    resolver: zodResolver(createCoordinatorFiltersSchema(t as TFunction)),
    mode: 'onChange',
  });

  const onViewSuccessfullyFetched = useCallback(
    (v: View) => {
      const normalizedFilters = normalizeViewFilters(v.filters, t);
      form.reset({ ...FILTERS_DEFAULT_VALUES, ...normalizedFilters });
    },
    [form, t],
  );

  const {
    moduleQuery: {
      data: moduleConfiguration,
      isLoading: isLoadingModuleConfiguration,
    },
  } = useModuleConfiguration();

  const { viewId } = useParams();
  const {
    currentView,
    isLoadingCurrentView,
    saveViewMutation,
    createViewMutation,
  } = useViews(viewId, onViewSuccessfullyFetched);

  const formValues = form.watch();

  const {
    query,
    pagination,
    Pagination,
    Search,
    order,
    orderBy,
    HuTableSortingHeader,
    normalizedCurrentViewFilters,
    setFilterParams,
    resetFilterParams,
    paginationForm,
  } = useServiceItemSearchParams(setAppliedFilters, form, currentView);

  const params = useMemo(
    () => ({
      q: query || undefined,
      page: pagination.page,
      limit: pagination.limit,
      order: order === 'ASC' ? 'ASC' : ('DESC' as const),
      orderBy,
      role: TasksType.AGENT,
      ...getFilterParams(appliedFilters),
    }),
    [appliedFilters, orderBy, order, pagination.page, query, pagination.limit],
  );

  const {
    handleOpenMultipleAssignmentMenu,
    handleOpenSingleAssignmentMenu,
    selectedTasks,
    setSelectedTasks,
    SingleAssignmentPopoverComponent,
    MultipleAssignmentPopoverComponent,
    multipleAssignmentConfirmationModal,
    singleAssignmentConfirmationModal,
  } = useAgentReassignment<Task>(params);

  const {
    data: tasks,
    isPreviousData,
    isLoading: isLoadingTasks,
    refetch,
    isError,
  } = useQuery(
    serviceManagementKeys.tasks.list(params),
    () => getTasks({ ...params, usePage: true }),
    { keepPreviousData: true, select: response => response.data },
  );

  useEffect(() => {
    logEvent(EventName.SERVICE_MGMT_AGENT_WORKSPACE_VIEW, {
      origin: isMobile() ? PlatformType.MOBILE : PlatformType.WEB,
      role: ServiceManagementRole.AGENT,
    });
  }, []);

  useTaskCommentsUpdater({
    socket,
    params,
    event: EVENTS_SOCKETS.SERVICE_MANAGER_TASK_NEW_COMMENT,
  });
  useTaskStateListUpdater({ socket, params });

  const handleRowClick = (task: Task) =>
    navigate(serviceManagementRoutes.agentSide.detail(task.id), {
      state: { navigatedFromServiceMgmt: true },
    });

  const handleCheckboxClick = (task: Task) => {
    setSelectedTasks(prevSelected => {
      const isSelected = prevSelected.includes(task);
      if (isSelected)
        return prevSelected.filter(prevTask => prevTask.id !== task.id);
      return [...prevSelected, task];
    });
  };

  const handleSelectAll = () => {
    const selectableTasks =
      tasks?.items.filter(task => !task.state.terminal) ?? [];
    setSelectedTasks(prevSelected =>
      prevSelected.length === selectableTasks.length &&
      tasks?.count &&
      tasks.count > 0
        ? []
        : selectableTasks,
    );
  };

  const handleOpenSingleReassign = (taskToReasign: Task, index: number) => {
    const el = document.getElementById(`id-agent-row-${index}`);
    if (el) handleOpenSingleAssignmentMenu(el, taskToReasign);
  };

  const assignButtonDisabled = useMemo(() => {
    const serviceItemId = selectedTasks[0]?.catalogItem?.id;
    if (!serviceItemId) return true;
    return selectedTasks.some(task => task.catalogItem.id !== serviceItemId);
  }, [selectedTasks]);

  const appliedFiltersCount = useMemo(
    () =>
      Object.values(appliedFilters ?? {}).filter(value =>
        value !== null && Array.isArray(value) ? value.length > 0 : value,
      ).length,
    [appliedFilters],
  );

  const handleCloseFilterDrawer = () => {
    setFilterDrawerOpen(false);
    form.reset({ ...appliedFilters });
  };

  const handleResetFilters = () => {
    if (currentView) {
      form.reset({
        ...FILTERS_DEFAULT_VALUES,
        ...normalizedCurrentViewFilters,
      });
    } else {
      form.reset({ ...FILTERS_DEFAULT_VALUES });
    }
  };

  const handleApplyFilters = () => {
    const filterValuesToApply = form.getValues();
    setAppliedFilters(filterValuesToApply);
    setFilterParams(filterValuesToApply);
    setFilterDrawerOpen(false);
  };

  const handleDismissNewFilters = () => {
    form.reset({ ...FILTERS_DEFAULT_VALUES, ...normalizedCurrentViewFilters });
    setAppliedFilters({
      ...FILTERS_DEFAULT_VALUES,
      ...normalizedCurrentViewFilters,
    });
    setFilterParams(normalizedCurrentViewFilters);
    if (!viewId) setAppliedFilters(null);
  };

  // Ref pattern to break the circular dependency between handleConfirmSaveViewChanges
  // and closeConfirmSaveViewModal (each needs the other at definition time).
  // noop default replaced synchronously after useConfirmSaveViewModal resolves
  const closeConfirmSaveViewModalRef = useRef<() => void>(() => {
    /* noop */
  });

  const handleConfirmSaveViewChanges = () => {
    if (!currentView) return;
    saveViewMutation.mutate(
      { id: currentView.id, filters: form.getValues(), name: currentView.name },
      {
        onSuccess: () => {
          closeConfirmSaveViewModalRef.current();
          alertRef.current?.closeMenu();
          resetFilterParams();
        },
      },
    );
  };

  const handleCreateNewView = (newName: string) => {
    createViewMutation.mutate(
      { name: newName, ...form.getValues() },
      {
        onSuccess: () => {
          resetFilterParams();
          closeCreateNewViewModal();
          alertRef.current?.closeMenu();
        },
      },
    );
  };

  useEffect(() => {
    const handler = setTimeout(() => {
      if (isLoadingCurrentView || isLoadingTasks) {
        setStableSelectedViewHasNewFilters(false);
        return;
      }
      if (
        appliedFilters == null ||
        isEqual(appliedFilters, FILTERS_DEFAULT_VALUES)
      ) {
        setStableSelectedViewHasNewFilters(false);
        return;
      }
      setStableSelectedViewHasNewFilters(
        !isEqual(normalizedCurrentViewFilters, appliedFilters),
      );
    }, 200);
    return () => clearTimeout(handler);
  }, [
    appliedFilters,
    normalizedCurrentViewFilters,
    isLoadingCurrentView,
    isLoadingTasks,
  ]);

  const handleSelectBaseView = () => {
    if (!viewId) return;
    setAppliedFilters(null);
    form.reset({ ...FILTERS_DEFAULT_VALUES });
    navigate(serviceManagementRoutes.agentWorkspace());
  };

  const handleSelectView = (selectedViewId: string) => {
    setAppliedFilters(null);
    form.reset({ ...FILTERS_DEFAULT_VALUES });
    navigate(serviceManagementRoutes.agentSide.viewDetail(selectedViewId));
  };

  const {
    confirmSaveViewModal,
    openConfirmSaveViewModal,
    closeConfirmSaveViewModal,
  } = useConfirmSaveViewModal({
    onConfirm: handleConfirmSaveViewChanges,
    isLoading: saveViewMutation.isLoading,
  });

  closeConfirmSaveViewModalRef.current = closeConfirmSaveViewModal;

  const handleSaveAsNewView = () => openCreateNewViewModal();
  const handleSaveViewChanges = () => openConfirmSaveViewModal();

  const {
    openInputNameModal: openCreateNewViewModal,
    closeInputNameModal: closeCreateNewViewModal,
  } = useViewInputNameModal({
    title: t('creating_new_view'),
    currentName: '',
    loading: createViewMutation.isLoading,
    onApply: handleCreateNewView,
    onClose: () => closeCreateNewViewModal(),
    primaryButtonProps: { variant: 'primary', children: t('create_view') },
    secondaryButtonProps: { variant: 'text', children: t('cancel') },
  });

  const hasFilters = Boolean(query || appliedFiltersCount > 0);
  const hasSlasConfigured = Boolean(moduleConfiguration?.slaEnabled);

  const allChecked = useMemo(() => {
    const selectableTasks =
      tasks?.items.filter(task => !task.state.terminal) ?? [];
    return (
      selectedTasks?.length > 0 &&
      !!tasks?.count &&
      tasks.count > 0 &&
      selectedTasks.length === selectableTasks.length
    );
  }, [selectedTasks, tasks]);

  const resetFiltersDisabled = useMemo(() => {
    if (!viewId) return false;
    return isEqual(normalizedCurrentViewFilters, formValues);
  }, [viewId, normalizedCurrentViewFilters, formValues]);

  return {
    HugoThemeProvider,
    isSidebarCollapsed,
    setIsSidebarCollapsed,
    filterDrawerOpen,
    setFilterDrawerOpen,
    appliedFilters,
    appliedFiltersCount,
    stableSelectedViewHasNewFilters,
    downloadReportDrawerOpen,
    setDownloadReportDrawerOpen,
    alertRef,
    form,
    paginationForm,
    Search,
    Pagination,
    HuTableSortingHeader,
    currentView,
    isLoadingCurrentView,
    viewId,
    tasks,
    isLoadingTasks,
    isPreviousData,
    isError,
    refetch,
    selectedTasks,
    query,
    isLoadingModuleConfiguration,
    hasSlasConfigured,
    hasFilters,
    allChecked,
    assignButtonDisabled,
    resetFiltersDisabled,
    canDownloadTaskReport,
    SingleAssignmentPopoverComponent,
    MultipleAssignmentPopoverComponent,
    multipleAssignmentConfirmationModal,
    singleAssignmentConfirmationModal,
    confirmSaveViewModal,
    handleRowClick,
    handleCheckboxClick,
    handleSelectAll,
    handleOpenSingleReassign,
    handleCloseFilterDrawer,
    handleResetFilters,
    handleApplyFilters,
    handleDismissNewFilters,
    handleSaveAsNewView,
    handleSaveViewChanges,
    handleSelectBaseView,
    handleSelectView,
    handleOpenMultipleAssignmentMenu,
  };
};
