import { StoreAction } from 'store/utils/actions';
import { handleRequest } from 'store/utils/reducers';
import produce from 'immer';
import _ from 'lodash';
import { handlePagesCompletion, handlePagesSearch } from 'store/utils/adminHelpers';
import { clone } from 'store/utils/helper';
import actions from './actions';

interface ParagraphState {
  list: Record<string, any>;
  user: Record<string, any>;
  search: Record<string, any>;
}

export const initialState: ParagraphState = {
  list: null,
  user: null,
};

export const handleList = (list?: Record<string, any>[]): object[] => {
  const newList = [];

  if (list) {
    list.forEach(
      (item: Record<string, any>): Record<string, any> => {
        const content = item.content;
        newList.push({
          ...item,
          content: typeof content === 'string' ? JSON.parse(content) : content,
        });
      },
    );
  }
  return newList;
};

const handeNew = (draft: ParagraphState, element: Record<string, any>): object[] => {
  const list = draft.list && draft.list.data;
  if (!list) return;

  // eslint-disable-next-line
  const index = _.findIndex(list, item => item.id == (element && element.id));

  if (index < 0) {
    list.push(element);
  } else {
    list.splice(index, 1, element);
  }

  if (draft) draft.list.data = handleList(list);
};

const handleDelete = (draft: ParagraphState, id: string): object[] => {
  const list = draft.list && draft.list.data;
  if (!list) return;

  // eslint-disable-next-line
  _.remove(list, item => item.id == id);

  draft.list.data = handleList(list);
};

/**
 * @param {boolean} options.forceClose - force item to be closed
 * @param {string} options.filter - filter to apply (hide or not elements)
 */
const handleSearch = (draft, options) => {
  options = options || {};
  options.key = 'list';
  handlePagesSearch(draft, options);
};

const reducer = (state: ParagraphState = initialState, action: StoreAction): ParagraphState =>
  produce(
    state,
    (draft: ParagraphState): ParagraphState => {
      switch (action.type) {
        case actions.list.request.constant: {
          // reset for first call
          const reset = action.payload && action.payload.reset;
          // force close can be given
          const forceClose = action.payload && action.payload.forceClose;
          handleRequest(draft, action, 'list', reset);
          draft.list.forceClose = forceClose;
          break;
        }
        case actions.list.result.constant: {
          draft.list.data = handleList(action.payload);
          draft.list.loaded = true;
          draft.list.loading = false;

          const currentSearch = draft.search && draft.search.filter;
          const forceClose = draft.pages.forceClose;

          handleSearch(draft, {
            forceClose,
            filter: currentSearch,
          });
          handlePagesCompletion(draft.pages.data);
          break;
        }
        case actions.me.request.constant:
          handleRequest(draft, action, 'user');
          break;
        case actions.me.result.constant:
          draft.user = {
            data: action.payload,
            loaded: true,
            loading: false,
          };
          break;
        case actions.add.result.constant:
          handeNew(draft, action.payload);
          break;
        case actions.update.result.constant: {
          const currentSearch = draft.search && draft.search.filter;

          handeNew(draft, action.payload);
          handleSearch(draft, {
            filter: currentSearch,
          });
          handlePagesCompletion(draft.list.data);
          break;
        }
        case actions.search.constant:
          handleSearch(draft, {
            filter: action.payload,
            forceClose: !action.payload,
          });
          break;
        case actions.delete.result.constant:
          handleDelete(draft, action.payload);
          break;
        case actions.logout.request.constant:
          draft.user = null;
          break;
        default:
      }
    },
  );

export default reducer;
