import { useMemo } from 'react';
import { useInfiniteQuery, useQuery } from 'react-query';
import { useNavigate } from 'react-router';

import { useQueryState } from 'nuqs';
import { useDebounce } from '@material-hu/hooks/useDebounce';

import { logEvent } from 'src/config/logging';
import { queryClient } from 'src/config/react-query';
import useGeneralError from 'src/hooks/useGeneralError';
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 {
  getCategories,
  getSegmentedServiceItems,
} from 'src/pages/dashboard/serviceManagement/services';
import {
  type Category,
  CategoryOrderBy,
  PlatformType,
  type ServiceItem,
  ServiceItemDesignLayout,
  ServiceItemStatus,
  ServiceManagementRole,
} from 'src/pages/dashboard/serviceManagement/types';
import { EventName } from 'src/types/amplitude';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { isMobile } from 'src/utils/recognitions';

import { useModuleConfiguration } from '../../../contexts/ModuleConfigurationContext';

const ITEMS_PER_PAGE = 12;

type ServiceItemsPage = {
  data?: { page?: number; totalPages?: number; items?: ServiceItem[] };
};

export const useServiceItems = () => {
  const navigate = useNavigate();
  const { t } = useLokaliseTranslation('service_management');
  const showGeneralError = useGeneralError();
  const HugoThemeProvider = useHuGoTheme();

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

  const [designType, setDesignType] = useLocalStorage(
    'service-item-design-type',
    ServiceItemDesignLayout.GRID,
  );

  const [selectedCategoryId, setSelectedCategoryId] = useQueryState(
    'category',
    {
      defaultValue: '',
    },
  );
  const [query, setQuery] = useQueryState('q', { defaultValue: '' });

  const debouncedQuery = useDebounce(query);

  const { data: categoriesData, isLoading: isLoadingCategories } = useQuery(
    serviceManagementKeys.categories.orderedList(
      moduleConfiguration?.categoryOrderBy || CategoryOrderBy.NAME,
    ),
    () => getCategories(moduleConfiguration?.categoryOrderBy),
    {
      keepPreviousData: true,
      select: response => response.data,
      enabled: !isLoadingModuleConfig,
    },
  );

  const {
    data,
    isLoading: isLoadingCatalogItems,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(
    serviceManagementKeys.serviceItems.list({
      query: debouncedQuery,
      categoryId: selectedCategoryId,
    }),
    ({ pageParam = 1 }) =>
      getSegmentedServiceItems({
        page: pageParam,
        query: debouncedQuery,
        categoryId: selectedCategoryId,
        limit: ITEMS_PER_PAGE,
        applyVisibilityRule: true,
        applyCandidateAgentRule: false,
        includeAssigned: false,
        status: ServiceItemStatus.ACTIVE,
      }),
    {
      getNextPageParam: (lastPage: ServiceItemsPage) => {
        const currentPage = lastPage.data?.page;
        const totalPages = lastPage.data?.totalPages;
        return currentPage && totalPages && currentPage < totalPages
          ? currentPage + 1
          : undefined;
      },
      onError: (err: unknown) => {
        if (moduleConfiguration?.stateMachineEnabled) {
          showGeneralError(err, t('error_loading_catalog_items'));
        }
      },
      keepPreviousData: true,
    },
  );

  const handleUpdateCurrentCategory = (category?: Category) =>
    setSelectedCategoryId(category?.id || '');

  const handleChangeDesignType = (
    _: React.MouseEvent<HTMLElement>,
    newDesignType: ServiceItemDesignLayout,
  ) => {
    if (newDesignType && newDesignType !== designType) {
      setDesignType(newDesignType);
    }
  };

  const handleStartServiceItem = (serviceItem: ServiceItem) => {
    navigate(serviceManagementRoutes.userSide.serviceItem(serviceItem.id), {
      state: { navigatedFromServiceItems: true },
    });
    logEvent(EventName.SERVICE_MGMT_SERVICE_SELECTED, {
      origin: isMobile() ? PlatformType.MOBILE : PlatformType.WEB,
      role: ServiceManagementRole.INITIATOR,
      serviceId: serviceItem.id,
      serviceName: serviceItem.name,
      categoryId: serviceItem.category?.id,
      categoryName: serviceItem.category?.name,
    });
  };

  const handleNavigateToServicePortal = () => {
    queryClient.invalidateQueries(serviceManagementKeys.tasks.all());
    navigate(serviceManagementRoutes.servicePortal());
  };

  const currentCategory = useMemo(() => {
    if (!categoriesData) return null;
    return categoriesData.find(c => c.id === selectedCategoryId) ?? null;
  }, [categoriesData, selectedCategoryId]);

  const showNoServiceItems =
    !isLoadingCatalogItems &&
    !debouncedQuery &&
    !query &&
    !data?.pages[0]?.data?.items?.length;

  const showAll = !currentCategory && !selectedCategoryId;

  return {
    HugoThemeProvider,
    designType,
    query,
    setQuery,
    categoriesData,
    isLoadingCategories,
    isLoadingModuleConfig,
    data,
    isLoadingCatalogItems,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    currentCategory,
    showNoServiceItems,
    showAll,
    handleUpdateCurrentCategory,
    handleChangeDesignType,
    handleStartServiceItem,
    handleNavigateToServicePortal,
  };
};
