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

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

import { createChart, createCountries, createDevices, createTotal } from '../../helpers/exportCSV';
import * as selectors from '../selectors';
import { exportToCSVAction } from '../slices';
import { saveBlobAsFile } from '@/modules/@common/helpers/file-saver';
import { getUserTimezoneSelector } from '@/modules/@common/user/redux/selectors';
import { showNotificationAction } from '@/modules/layout/redux/slices';

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

      const users = selectors.usersSelector(state);
      const totalMinutes = selectors.totalMinutesSelector(state);
      const averageMinutes = selectors.averageMinutesSelector(state);
      const averageMinutesPercent = selectors.averageMinutesPercentSelector(state);
      const desktop = selectors.desktopSelector(state);
      const mobile = selectors.mobileSelector(state);
      const countries = selectors.countriesSelector(state);
      const chartData = selectors.chartDataSelector(state);

      const userTimezone = getUserTimezoneSelector(state$.value);

      const stream$ = defer(async () => {
        const JSZip = (await import('jszip')).default;

        const zip = new JSZip();
        zip.file(
          'Total.csv',
          createTotal({
            users,
            totalMinutes,
            averageMinutes,
            averageMinutesPercent,
          }),
        );
        zip.file('Devices.csv', createDevices({ desktop, mobile }));
        zip.file('Countries.csv', createCountries({ countries }));
        zip.file('Chart.csv', createChart({ chartData, userTimezone }));
        return zip.generateAsync({ type: 'blob' });
      }).pipe(
        switchMap((content) => {
          saveBlobAsFile(content, 'live-events-past.zip');

          return concat(
            of(
              showNotificationAction({
                type: TYPE_SUCCESS,
                message: 'Download was successful',
              }),
            ),
          );
        }),
      );

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