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

import { PCN_GET_MARKETPLACE_DASHBOARD } from '@/modules/@common/acl/constants';

import { getHubsAndDemandAccountsAction, setHubsAndDemandAccountsAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';

const selfServeQuery = `
  query MarketplaceHubsAndDemandAccounts {
    hubsAndDemandAccounts {
      records {
        id
        name
        mpSelfService
        demandAccount {
          id
          name
        }
      }
    }
  }
`;

const adminQuery = `
  query SearchDemandAccountsQuery(
    $from: Int,
    $size: Int,
    $query: String,
    $status: String
  ) {
    searchDemandAccounts(
      from: $from,
      size: $size,
      query: $query,
      status: $status
    ) {
      totalCount
      data {
        id
        name
      }
    }
  }
`;

export default (action$, state$) =>
  action$.pipe(
    ofType(getHubsAndDemandAccountsAction.type),
    debounce((action) => timer(action.payload?.search ? 1000 : 0)),
    switchMap(({ payload }) => {
      let params = {};
      const userPermissions = getUserPermissionsSelector(state$.value);
      const isAdminMP = hasPermission(PCN_GET_MARKETPLACE_DASHBOARD, userPermissions);

      if (isAdminMP) {
        params = {
          variables: {
            size: 30,
            from: 0,
          },
        };

        if (payload?.search?.length) {
          params = {
            variables: {
              ...params.variables,
              query: payload.search,
            },
          };
        }
      }

      const stream$ = gqlRequest({
        query: isAdminMP ? adminQuery : selfServeQuery,
        ...params,
      }).pipe(
        switchMap(({ data, errors }) => {
          let actions = [];

          if (!errors.length) {
            if (isAdminMP) {
              actions = [
                of(
                  setHubsAndDemandAccountsAction({
                    userDemandAccounts: data.searchDemandAccounts.data,
                  }),
                ),
              ];
            }

            if (!isAdminMP) {
              const demandAccounts = data.hubsAndDemandAccounts.records?.map((item) => item?.demandAccount);

              actions = [
                of(
                  setHubsAndDemandAccountsAction({
                    userHubs: data.hubsAndDemandAccounts.records,
                    userDemandAccounts: Object.values(
                      demandAccounts.reduce((acc, obj) => ({ ...acc, [obj.id]: obj }), {}),
                    ),
                  }),
                ),
              ];
            }
          }

          return concat(...actions);
        }),
      );

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