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

import { TRENDING } from '@/modules/editorial/constants/video';
import { FILTER_COMPONENTS_NAMES, VIDEO_DURATION_LABELS } from '@/modules/editorial/editorialSearchFilter/constants';

import { getVideoDurationFilterEnumValue } from '../../../../common/helpers';
import { aiPlaylistSelector } from '../selectors';
import { getAiFiltersAction, setAiFiltersAction } from '../slices';
import { getLanguageOptions } from '@/modules/@common/helpers/videoLangs';
import { findNodes, getIAB } from '@/modules/@common/iab/helpers';
import { gqlRequest } from '@/modules/@common/request';
import {
  configAction,
  configChangedEventAction,
  isFilterDirtyAction,
} from '@/modules/editorial/editorialSearchFilter/filterContainer/redux/slices';

import {
  getDefaultConfig,
  getEmptySearchOrderConfig,
  timeValueMap,
} from '@/modules/editorial/editorialSearchFilter/filterConfig';

const queryGQL = `
  query getAiFilters(
    $watchId: Int!,
    $channelId: Int!,
    $aiPlaylistId: Int!,
  ) {
    getAiFilters(
      watchId: $watchId,
      channelId: $channelId,
      aiPlaylistId: $aiPlaylistId,
    ) {
      id
      videoFilterValues {
        id
        videoFilterId
        type
        value
        action
        extra
        color
        name
      }
    }
  }
`;

const ACTIONS = {
  INCLUDE: true,
  EXCLUDE: false,
};

const configUpdater = {
  IAB: (config, { value, action }) => ({
    ...config,
    categories: {
      ...config.categories,
      filters: [
        {
          ...config.categories.filters[0],
          value: [
            ...config.categories.filters[0].value,
            {
              id: findNodes(getIAB(), [value])[0].id,
              name: findNodes(getIAB(), [value])[0].name,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  PEOPLE: (config, { value, action }) => ({
    ...config,
    people: {
      ...config.people,
      filters: [
        {
          ...config.people.filters[0],
          value: [
            ...config.people.filters[0].value,
            {
              value,
              label: value,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  BRANDS: (config, { value, action }) => ({
    ...config,
    brands: {
      ...config.brands,
      filters: [
        {
          ...config.brands.filters[0],
          value: [
            ...config.brands.filters[0].value,
            {
              value,
              label: value,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  BRAND_SAFETY: (config, { value, action }) => ({
    ...config,
    brandSafety: {
      ...config.brandSafety,
      filters: [
        {
          ...config.brandSafety.filters[0],
          value: [
            ...config.brandSafety.filters[0].value,
            {
              value,
              label: value,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  LABEL: (config, { value, action, color, name, extra }) => ({
    ...config,
    labels: {
      ...config.labels,
      filters: [
        {
          ...config.labels.filters[0],
          value: [
            ...config.labels.filters[0].value,
            {
              value: value.split(':').slice(1).join(':'),
              label: value.split(':').slice(1).join(':'),
              labelId: extra,
              name,
              color,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  KEYWORDS: (config, { value, action, color, name, extra }) => ({
    ...config,
    keywords: {
      ...config.keywords,
      filters: [
        {
          ...config.keywords.filters[0],
          value: [
            ...config.keywords.filters[0].value,
            {
              value,
              label: value,
              labelId: extra,
              name,
              color,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  LANG: (config, { value, action }) => ({
    ...config,
    languages: {
      ...config.languages,
      filters: [
        {
          ...config.languages.filters[0],
          value: [
            ...config.languages.filters[0].value,
            {
              value,
              label: getLanguageOptions().find((lang) => lang.value === value).label,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  FEED: (config, { value, action }) => ({
    ...config,
    source: {
      ...config.source,
      filters: [
        {
          ...config.source.filters[0],
          value: [
            ...config.source.filters[0].value,
            {
              value,
              label: value,
              include: ACTIONS[action],
            },
          ],
        },
      ],
    },
  }),
  EVERGREEN: (config, { value }) => ({
    ...config,
    evergreen: {
      ...config.evergreen,
      filters: [
        {
          ...config.evergreen.filters[0],
          value: [
            {
              value: value === 'true' ? 'EVERGREEN' : 'NO_EVERGREEN',
              label: value === 'true' ? 'Evergreen' : 'Non Evergreen',
            },
          ],
        },
      ],
    },
  }),
  TARGETING_STATUS: (config, { value }) => ({
    ...config,
    targetingStatus: {
      ...config.targetingStatus,
      filters: [
        {
          ...config.targetingStatus.filters[0],
          value: [{ label: 'Video Targeting', value }],
        },
      ],
    },
  }),
  MEDIA_TYPE: (config, { value }) => ({
    ...config,
    mediaType: {
      ...config.mediaType,
      filters: [
        {
          ...config.mediaType.filters[0],
          value: [{ label: 'Media Type', value }],
        },
      ],
    },
  }),
};

const getUpdatedConfig = (oldConfig, newConfig = []) => {
  const updatedConfig = {
    ...oldConfig,
  };

  const customTime = {
    filters: [
      {
        label: 'Custom',
        value: {},
        component: FILTER_COMPONENTS_NAMES.FilterTimePicker,
      },
    ],
  };

  const config = newConfig.reduce((acc, cur) => {
    if (configUpdater[cur.type]) {
      return configUpdater[cur.type](acc, cur);
    }
    return acc;
  }, updatedConfig);

  const duration = {};

  newConfig.forEach((item) => {
    if (item.type === 'TIME') {
      config.time = {
        filters: [timeValueMap[item.value]],
      };
    } else if (['START_DATE', 'END_DATE'].includes(item.type)) {
      customTime.filters[0].value[item.type === 'START_DATE' ? 'startDate' : 'endDate'] = dayjs(+item.value)
        .toDate()
        .getTime();
    }

    if (item.type === 'LENGTH_TO') {
      duration.to = item.value;
    }

    if (item.type === 'LENGTH_FROM') {
      duration.from = item.value;
    }

    if (item.type === 'VIDEO_AFFILIATION' && item.value === 'MY_VIDEOS') {
      config.videos = {
        filters: [{ label: 'My Videos', value: item.value }],
      };
    }
  });

  if (customTime.filters[0].value.startDate) {
    config.time = customTime;
  }

  const videoDurationFilterEnumValue = getVideoDurationFilterEnumValue(duration);
  if (videoDurationFilterEnumValue) {
    config.duration = {
      filters: [{ label: VIDEO_DURATION_LABELS[videoDurationFilterEnumValue], value: videoDurationFilterEnumValue }],
    };
  }

  return config;
};

export default (action$, state$) =>
  action$.pipe(
    ofType(getAiFiltersAction.type),
    concatMap(({ payload: { watchId, channelId, aiPlaylistId, withSearch = false } }) => {
      const aiPlaylist = aiPlaylistSelector(state$.value);

      const stream$ = gqlRequest({
        query: queryGQL,
        variables: {
          watchId,
          channelId,
          aiPlaylistId,
        },
      }).pipe(
        switchMap(({ data, errors }) => {
          const actions = [];
          if (!errors.length) {
            const { videoFilterValues } = data.getAiFilters;
            const config = getDefaultConfig();

            const defaultOrderConfig = getEmptySearchOrderConfig();

            const filterConfig = {
              ...config,
              ...defaultOrderConfig,
            };

            const updatedConfig = getUpdatedConfig(filterConfig, videoFilterValues);

            const playlistType = Object.keys(aiPlaylist).find((key) => aiPlaylist[key]?.id === aiPlaylistId);

            if (playlistType) {
              actions.push(
                of(
                  setAiFiltersAction({
                    [playlistType]: [...videoFilterValues],
                  }),
                ),
              );
            }

            if (playlistType === TRENDING) {
              updatedConfig.order.filters[0] = {
                label: 'Trending',
                value: 'trending',
                isSortable: false,
              };
            }

            if (withSearch) {
              actions.push(
                of(configAction(updatedConfig)),
                of(configChangedEventAction()),
                of(isFilterDirtyAction(true)),
              );
            }
          }

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

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