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

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

import * as actions from '../../../pages/homepage/actions/rules.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 after requesting a rule', () => {
    const action = { type: actions.REQUEST_RULE };
    const expectedState = { ...defaultState, isFetching: true };

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

  it('should return after requesting multiple rules', () => {
    const action = { type: actions.REQUEST_RULES };
    const expectedState = { ...defaultState, isFetching: true };

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

  it('should return state after receiving a rule', () => {
    const rule = {
      id: 1,
      name: 'Test rule',
      unread: 100,
      category: 1,
      url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
      favicon: 'https://cdn.arstechnica.net/favicon.ico',
    };

    const action = { type: actions.RECEIVE_RULE, rule };

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

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

  it('should return state after receiving multiple rules', () => {
    const rules = [
      {
        id: 1,
        name: 'Test rule',
        unread: 100,
        category: 1,
        url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
        favicon: 'https://cdn.arstechnica.net/favicon.ico',
      },
      {
        id: 2,
        name: 'Another Test rule',
        unread: 444,
        category: 1,
        url: 'http://feeds.arstechnica.com/arstechnica/index?fmt=xml',
        favicon: 'https://cdn.arstechnica.net/favicon.ico',
      },
    ];

    const action = { type: actions.RECEIVE_RULES, rules };

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

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

  it('should return state after marking a post read', () => {
    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: { [rule.id]: rule },
    };

    const expectedState = {
      ...defaultState,
      items: { [rule.id]: { ...rule, unread: 99 } },
    };

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

  it('should return state after marking a category read', () => {
    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 action = {
      type: selectedActions.MARK_SECTION_READ,
      section: { ...category, type: constants.CATEGORY_TYPE },
    };

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

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

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

  it('should return state after marking a rule read', () => {
    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 action = {
      type: selectedActions.MARK_SECTION_READ,
      section: { ...rule, type: constants.RULE_TYPE },
    };

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

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

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