import { ofType } from 'redux-observable';
import { concat, EMPTY, of, timer } from 'rxjs';
import { debounce, switchMap } from 'rxjs/operators';

import { TEMPLATE_CATEGORY_ALL } from '@/modules/forms/constants';
import { GET_TEMPLATE_STATUS_INITIAL } from '@/modules/forms/forms/constants';

import * as formsSelector from '../selectors';
import { getTemplateGalleryAction, setFieldAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { getTemplateIds } from '@/modules/forms/forms/helpers/upsertLastUsedTemplates';

const query = `
  query GetFormTemplateGallery(
    $searchText: String
    $formTemplateCategoryIds: [Int]
  ) {
    getFormTemplateGallery(
      searchText: $searchText
      formTemplateCategoryIds: $formTemplateCategoryIds
    ) {
      records {
        id
        formTemplateCategory {
          id
          name
        }
        account {
          id
          name
        }
        name
        title
        logo
        updatedAt
        updatedBy
      }
      recordsTotal
    }
  }
`;

const getResponse = ({ data: { getFormTemplateGallery } }) => getFormTemplateGallery;

export default (action$, state$) =>
  action$.pipe(
    ofType(getTemplateGalleryAction.type),
    debounce(() => {
      const templateSearchText = formsSelector.templateSearchTextSelector(state$.value);
      return timer(templateSearchText.length > 1 ? 1000 : 0);
    }),
    switchMap((action) => {
      const moduleState = state$.value;

      const templateSearchText = formsSelector.templateSearchTextSelector(moduleState);
      const templateCategory = formsSelector.templateCategorySelector(moduleState);

      const variables = {
        searchText: templateSearchText,
      };

      if (templateCategory !== TEMPLATE_CATEGORY_ALL) {
        variables.formTemplateCategoryIds = [templateCategory];
      }

      const stream$ = gqlRequest({
        query,
        variables,
      }).pipe(
        switchMap((response) => {
          if (!response.errors.length) {
            const { records: templates } = getResponse(response);
            const state = {
              templates,
            };

            if (action.payload === GET_TEMPLATE_STATUS_INITIAL) {
              const lastUsedTemplateIds = getTemplateIds();
              const lastUsed = templates.filter((template) => lastUsedTemplateIds.includes(template.id));

              if (lastUsed.length) {
                state.lastUsedTemplates = lastUsed;
              } else {
                // get random slice with 3 templates
                const maxLength = 3;
                const randomIndex = Math.floor(Math.random() * templates.length);
                const endIndex = randomIndex > maxLength ? randomIndex : maxLength;
                const startIndex = endIndex - maxLength;

                state.lastUsedTemplates = templates.slice(startIndex, endIndex);
              }
            }

            return of(setFieldAction(state));
          }

          return EMPTY;
        }),
      );

      return concat(stream$);
    }),
  );
