import { drugSchema } from '@/models/drugSchema';
import { apiPath } from '@/redux/apiPath';
import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
import { Drug } from '@/types/models';
import { ThunkConfig } from '@/types/store';
import { getErrorMessage } from '@/utils/getErrorMessage';
import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
import { createAsyncThunk } from '@reduxjs/toolkit';
import { z } from 'zod';
import { addNumbersToEntityNumberData } from '../entityNumber/entityNumber.slice';
import { DRUGS_FETCHING_ERROR_PREFIX, MULTI_DRUGS_FETCHING_ERROR_PREFIX } from './drugs.constants';

export const getDrugs = createAsyncThunk<Drug[] | undefined, string, ThunkConfig>(
  'project/getDrugs',
  async (searchQuery: string, { rejectWithValue }) => {
    try {
      const response = await axiosInstanceNewAPI.get<Drug[]>(
        apiPath.getDrugsStringWithQuery(searchQuery),
      );

      const isDataValid = validateDataUsingZodSchema(response.data, z.array(drugSchema));

      return isDataValid ? response.data : undefined;
    } catch (error) {
      const errorMessage = getErrorMessage({ error, prefix: DRUGS_FETCHING_ERROR_PREFIX });
      return rejectWithValue(errorMessage);
    }
  },
);

export const getMultiDrugs = createAsyncThunk<void, string[], ThunkConfig>(
  'project/getMultiDrugs',
  // eslint-disable-next-line consistent-return
  async (searchQueries, { dispatch, rejectWithValue }) => {
    try {
      const asyncGetDrugsFunctions = searchQueries.map(searchQuery =>
        dispatch(getDrugs(searchQuery)),
      );

      const drugsDataActions = await Promise.all(asyncGetDrugsFunctions);

      const drugsTargetsData = drugsDataActions
        .map(drugsDataAction =>
          typeof drugsDataAction.payload === 'string' ? [] : drugsDataAction.payload || [],
        )
        .flat()
        .map(drug => drug.targets)
        .flat()
        .map(target => target.targetElements)
        .flat();

      const drugsIds = drugsTargetsData.map(d => d.fullName || d.elementId);
      dispatch(addNumbersToEntityNumberData(drugsIds));
    } catch (error) {
      const errorMessage = getErrorMessage({ error, prefix: MULTI_DRUGS_FETCHING_ERROR_PREFIX });

      return rejectWithValue(errorMessage);
    }
  },
);