import Router from 'next/router';
import { ofType } from 'redux-observable';
import { concat, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';

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

import {
  createFeesListInput,
  createIncludeExcludeInput,
  getIncludeOrExclude,
} from '../../helpers/createDemandTagRequestBody';
import * as selectors from '../selectors';
import { createAdvertiserAction, setFieldAction } from '../slices';
import { gqlRequest } from '@/modules/@common/request';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';
import { showNotificationAction } from '@/modules/layout/redux/slices';
import { uploadFileAndGetDownloadUrl$ } from '@/modules/marketplace/common/helpers/uploadToS3';

const query = `
  mutation CreateSelfServeAdvertiser(
    $name: String,
    $daccountId: String,
    $include: MarketplaceTargetingInputType,
    $exclude: MarketplaceTargetingInputType,
    $revShare: MarketplacePricingInputType,
    $tier: Int,
    $profitability: Boolean,
    $frequencyCapAdjustment: Boolean,
    $frequencyCapAdjustmentPerSupply: Boolean,
    $pbsEnabled: Boolean,
    $frequencyCapAdjustmentThreshold: Float,
    $logo: String,
  ) {
    createSelfServeAdvertiser(
      name: $name,
      daccountId: $daccountId,
      include: $include,
      exclude: $exclude,
      revShare: $revShare,
      tier: $tier,
      profitability: $profitability,
      frequencyCapAdjustment: $frequencyCapAdjustment,
      pbsEnabled: $pbsEnabled,
      frequencyCapAdjustmentPerSupply: $frequencyCapAdjustmentPerSupply,
      frequencyCapAdjustmentThreshold: $frequencyCapAdjustmentThreshold,
      logo: $logo,
    ) {
      id
      name
    }
  }
`;

const createIncludeExcludeGeoObject = (countriesList, isInclude = true) =>
  createIncludeExcludeInput({
    geo: {
      key: 'geo',
      value: getIncludeOrExclude(isInclude, countriesList),
    },
  });

export default (action$, state$) =>
  action$.pipe(
    ofType(createAdvertiserAction.type),
    switchMap(() => {
      const state = state$.value;

      const advertiserSettings = selectors.advertiserSettingsSelector(state);
      const userPermissions = getUserPermissionsSelector(state);

      const isAdminMP = hasPermission(PCN_GET_MARKETPLACE_DASHBOARD, userPermissions);

      const {
        demandAccountId,
        name,
        countries,
        tier,
        pbsEnabled,
        profitability,
        revShare,
        frequencyCapAdjustment,
        frequencyCapAdjustmentPerSupply,
        frequencyCapAdjustmentThreshold,
        logo,
        logoFile,
      } = advertiserSettings;

      const createAdvertiser$ = (logoUrl) =>
        gqlRequest({
          query,
          variables: {
            name,
            pbsEnabled,
            frequencyCapAdjustment,
            daccountId: demandAccountId?.toString(),
            logo: logoUrl ?? logo,
            include: createIncludeExcludeGeoObject(countries, true),
            exclude: createIncludeExcludeGeoObject(countries, false),
            ...(isAdminMP && { tier, profitability }),
            ...(revShare?.length && {
              revShare: createFeesListInput(revShare)[0],
            }),
            ...(frequencyCapAdjustment && { frequencyCapAdjustmentThreshold, frequencyCapAdjustmentPerSupply }),
          },
        }).pipe(
          switchMap(({ data, errors }) => {
            let actions = [];

            if (!errors.length) {
              const link = `/demand/${demandAccountId}/advertisers/${data.createSelfServeAdvertiser?.id}`;

              Router.push(link);

              actions = [
                of(
                  showNotificationAction({
                    type: TYPE_SUCCESS,
                    message: 'Advertiser created',
                  }),
                ),
              ];
            }

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

      const stream$ = !logoFile
        ? createAdvertiser$(null)
        : uploadFileAndGetDownloadUrl$({ file: logoFile }).pipe(
            switchMap((downloadUrl) => createAdvertiser$(downloadUrl)),
          );

      return concat(of(setFieldAction({ isLoading: true })), stream$, of(setFieldAction({ isLoading: false })));
    }),
  );
