import { InfiniteData } from 'react-query';

import { AxiosResponse } from 'axios';

import { queryClient } from 'src/config/react-query';
import {
  FormAvailableItem,
  FormPaginationAvailableListResponse,
  FormType,
} from 'src/types/forms';
import { Updater } from 'src/types/queries';
import { SurveysNotificationsResponse } from 'src/types/surveys';
import { findIndexOnPaginatedPages } from 'src/utils/pages';
import { functionalUpdate } from 'src/utils/queries';

import { formKeys } from 'src/components/dashboard/form/queries';

export const surveyKeys = {
  all: () => ['surveys'],
  notifications: {
    all: () => [...surveyKeys.all(), 'notifications'],
    module: () => [...surveyKeys.notifications.all(), 'module'],
  },
};

export const setAvailableSurvey = (
  surveyId: number,
  updater: Updater<FormAvailableItem>,
) => {
  queryClient.setQueryData(
    formKeys.listAvailable(FormType.SURVEY),
    (
      oldData: InfiniteData<AxiosResponse<FormPaginationAvailableListResponse>>,
    ) => {
      if (!oldData) return oldData;

      const [pageIndex, surveyIndex] =
        findIndexOnPaginatedPages<FormAvailableItem>(
          oldData.pages,
          item => item.id === surveyId,
        );

      if (pageIndex !== -1 && surveyIndex !== -1) {
        oldData.pages[pageIndex].data.items[surveyIndex] = functionalUpdate(
          updater,
          oldData.pages[pageIndex].data.items[surveyIndex],
        );
      }

      return oldData;
    },
  );
};

export const dropAvailableSurvey = (surveyId: number) => {
  queryClient.setQueryData(
    formKeys.listAvailable(FormType.SURVEY),
    (
      oldData: InfiniteData<AxiosResponse<FormPaginationAvailableListResponse>>,
    ) => {
      if (!oldData) return oldData;

      const [pageIndex, surveyIndex] =
        findIndexOnPaginatedPages<FormAvailableItem>(
          oldData.pages,
          item => item.id === surveyId,
        );

      if (pageIndex !== -1 && surveyIndex !== -1) {
        oldData.pages[pageIndex].data.items.splice(surveyIndex, 1);
      }

      return oldData;
    },
  );
};

export const updateAvailableSurveyRemainingAttemps = (
  surveyId: number,
  remainingAttempts: number,
) => {
  if (remainingAttempts <= 0) {
    dropAvailableSurvey(surveyId);
    removeSurveyNotification();
    queryClient.invalidateQueries(formKeys.listCompleted(FormType.SURVEY));

    return;
  }

  setAvailableSurvey(surveyId, oldData => {
    if (!oldData) return oldData;

    oldData.numberOfAttemptsAllowed = remainingAttempts;

    return oldData;
  });
};

export const invalidateAvailableSurveyList = () => {
  queryClient.invalidateQueries(formKeys.listAvailable(FormType.SURVEY));
};

// Notifications

export const addSurveyNotification = (count: number = 1) => {
  queryClient.setQueryData(
    surveyKeys.notifications.module(),
    (oldData: AxiosResponse<SurveysNotificationsResponse>) => {
      if (!oldData?.data) return oldData;

      oldData.data.surveyNotifications += count;

      return oldData;
    },
  );
};

export const removeSurveyNotification = (count: number = 1) => {
  queryClient.setQueryData(
    surveyKeys.notifications.module(),
    (oldData: AxiosResponse<SurveysNotificationsResponse>) => {
      if (!oldData?.data) return oldData;

      oldData.data.surveyNotifications -= count;

      return oldData;
    },
  );
};

export const invalidateSurveysList = () => {
  queryClient.invalidateQueries(formKeys.listAvailable(FormType.SURVEY));
  queryClient.invalidateQueries(formKeys.listCompleted(FormType.SURVEY));
};

export const invalidateSurveysNotifications = () => {
  queryClient.invalidateQueries(surveyKeys.notifications.module());
};
