import { categories as reducer } from '../../../pages/homepage/reducers/categories.js';

import { objectsFromArray } from '../../../utils.js';

import * as actions from '../../../pages/homepage/actions/categories.js';
import * as postActions from '../../../pages/homepage/actions/posts.js';
import * as selectedActions from '../../../pages/homepage/actions/selected.js';
import * as constants from '../../../pages/homepage/constants.js';

const defaultState = { items: {}, isFetching: false };

describe('category reducer', () => {
  it('should return default state', () => {
    expect(reducer(undefined, {})).toEqual(defaultState);
  });

  it('should return state after receiving category', () => {
    const receivedCategory = { id: 9, name: 'Tech', unread: 291 };
    const action = { type: actions.RECEIVE_CATEGORY, category: receivedCategory };

    const expectedState = {
      ...defaultState,
      items: { [receivedCategory.id]: receivedCategory },
    };

    expect(reducer(undefined, action)).toEqual(expectedState);
  });

  it('should return state after receiving multiple categories', () => {
    const receivedCategories = [
      { id: 9, name: 'Tech', unread: 291 },
      { id: 2, name: 'World news', unread: 444 },
    ];

    const action = { type: actions.RECEIVE_CATEGORIES, categories: receivedCategories };

    const expectedCategories = objectsFromArray(receivedCategories, 'id');
    const expectedState = { ...defaultState, items: expectedCategories };

    expect(reducer(undefined, action)).toEqual(expectedState);
  });

  it('should return state after requesting a category', () => {
    const action = { type: actions.REQUEST_CATEGORY };

    const expectedState = { ...defaultState, isFetching: true };

    expect(reducer(undefined, action)).toEqual(expectedState);
  });

  it('should return state after requesting multiple categories', () => {
    const action = { type: actions.REQUEST_CATEGORIES };

    const expectedState = { ...defaultState, isFetching: true };

    expect(reducer(undefined, action)).toEqual(expectedState);
  });

  it('should return state after marking a post read with a category selected', () => {
    const category = {
      id: 9,
      name: 'Tech',
      unread: 291,
    };

    const post = {
      id: 2091,
      remoteIdentifier: 'https://www.bbc.co.uk/news/world-asia-china-51249208',
      title: 'China coronavirus spread is accelerating, Xi Jinping warns',
      body:
        'China\'s president tells a high-level meeting that the country faces a "grave situation".',
      author: null,
      publicationDate: '2020-01-26T05:54:14Z',
      url: 'https://www.bbc.co.uk/news/world-asia-china-51249208',
      rule: 4,
      read: false,
    };

    const action = {
      type: postActions.MARK_POST_READ,
      section: { ...category, type: constants.CATEGORY_TYPE },
      post,
    };

    const state = {
      ...defaultState,
      items: { [category.id]: { ...category } },
    };

    const expectedState = {
      ...defaultState,
      items: {
        [category.id]: { ...category, unread: 290 },
      },
    };

    expect(reducer(state, action)).toEqual(expectedState);
  });

  it('should return state after marking a post read with a rule selected', () => {
    const category = {
      id: 9,
      name: 'Tech',
      unread: 433,
    };

    const rule = {
      id: 1,
      name: 'Test rule',
      unread: 100,
      category: 9,
      url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
      favicon: 'https://cdn.arstechnica.net/favicon.ico',
    };

    const post = {
      id: 2182,
      remoteIdentifier: 'https://arstechnica.com/?p=1648871',
      title: 'Tesla needs to fix Autopilot safety flaws, demands Senator Markey',
      body:
        'It should be renamed and fitted with a real driver-monitoring system, he says.',
      author: 'Jonathan M. Gitlin',
      publicationDate: '2020-01-25T18:34:20Z',
      url: 'https://arstechnica.com/?p=1648871',
      rule: 1,
      read: false,
    };

    const action = {
      type: postActions.MARK_POST_READ,
      section: { ...rule, type: constants.RULE_TYPE },
      post,
    };

    const state = {
      ...defaultState,
      items: { [category.id]: { ...category } },
    };

    const expectedState = {
      ...defaultState,
      items: {
        [category.id]: { ...category, unread: 432 },
      },
    };

    expect(reducer(state, action)).toEqual(expectedState);
  });

  it('should return state after marking a section read with a category', () => {
    const category = {
      id: 9,
      name: 'Tech',
      unread: 433,
    };

    const action = {
      type: selectedActions.MARK_SECTION_READ,
      section: { ...category, type: constants.CATEGORY_TYPE },
    };

    const state = {
      ...defaultState,
      items: { [category.id]: { ...category } },
    };

    const expectedState = {
      ...defaultState,
      items: {
        [category.id]: { ...category, unread: 0 },
      },
    };

    expect(reducer(state, action)).toEqual(expectedState);
  });

  it('should return state after marking a section read with a rule', () => {
    const category = {
      id: 9,
      name: 'Tech',
      unread: 433,
    };

    const rule = {
      id: 1,
      name: 'Test rule',
      unread: 211,
      category: 9,
      url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
      favicon: 'https://cdn.arstechnica.net/favicon.ico',
    };

    const action = {
      type: selectedActions.MARK_SECTION_READ,
      section: { ...rule, type: constants.RULE_TYPE },
    };

    const state = {
      ...defaultState,
      items: { [category.id]: { ...category } },
    };

    const expectedState = {
      ...defaultState,
      items: {
        [category.id]: { ...category, unread: 222 },
      },
    };

    expect(reducer(state, action)).toEqual(expectedState);
  });
});
