import { List, Map } from 'immutable';
import { fetchListType, fetchType, editType } from './funcTools/crud';
import { createRequestReducer } from './funcTools/request';
import { mergeReducers, success } from './funcTools/tools';
import Filter from 'Types/filter';
import { liveFiltersMap } from 'Types/filter/newFilter';
import { filterMap, checkFilterValue, hasFilterApplied, getAppliedFilterIndex } from './search';
import Session from 'Types/session';

const name = "liveSearch";
const idKey = "searchId";

const FETCH_FILTER_SEARCH = fetchListType(`${name}/FILTER_SEARCH`);
const FETCH = fetchType(name);
const EDIT = editType(name);
const CLEAR_SEARCH = `${name}/CLEAR_SEARCH`;
const APPLY = `${name}/APPLY`;
const UPDATE_CURRENT_PAGE = `${name}/UPDATE_CURRENT_PAGE`;
const FETCH_SESSION_LIST = fetchListType(`${name}/FETCH_SESSION_LIST`);

const initialState = Map({
	list: List(),
	instance: new Filter({ filters: [], sort: '' }),
  filterSearchList: {},
  currentPage: 1,
  total: 0,
});

function reducer(state = initialState, action = {}) {
	switch (action.type) {
    case APPLY:
      return state.mergeIn(['instance'], action.filter);
    case EDIT:
      return state.mergeIn(['instance'], action.instance).set('currentPage', 1);
    case UPDATE_CURRENT_PAGE:
      return state.set('currentPage', action.page);
    case success(FETCH_SESSION_LIST):
      const { sessions, total } = action.data;
      const list = List(sessions).map(s => new Session(s));
      return state
        .set('list', list)
        .set('total', total);
    case success(FETCH_FILTER_SEARCH):
      const groupedList = action.data.reduce((acc, item) => {
        const { projectId, type, value } = item;
        const key = type;
        if (!acc[key]) {
          acc[key] = [];
        }
        acc[key].push({ projectId, value });
        return acc;
      }, {});
      return state.set('filterSearchList', groupedList);
	}
	return state;
}

export default mergeReducers(
	reducer,
	createRequestReducer({
		fetch: FETCH,
    fetchList: FETCH_SESSION_LIST,
    fetchFilterSearch: FETCH_FILTER_SEARCH
	}),
);

export const customSetSessions = (data) => ({
  type: success(FETCH_SESSION_LIST),
  data
})

const reduceThenFetchResource = actionCreator => (...args) => (dispatch, getState) => {
  dispatch(actionCreator(...args));
  const filter = getState().getIn([ 'liveSearch', 'instance']).toData();
  filter.filters = filter.filters.map(filterMap);
  filter.limit = 10;
  filter.page = getState().getIn([ 'liveSearch', 'currentPage']);

  return dispatch(fetchSessionList(filter));
};

export const fetchSessionList = (filter) => {
  return {
    types: FETCH_SESSION_LIST.array,
    call: client => client.post('/assist/sessions', filter),
  }
}

export const edit = reduceThenFetchResource((instance) => ({
  type: EDIT,
  instance,
}));

export const applyFilter = reduceThenFetchResource((filter) => ({
  type: APPLY,
  filter,
}));

export const fetchSessions = (filter) => (dispatch, getState) => {
  const _filter = filter ? filter : getState().getIn([ 'liveSearch', 'instance']);
  return dispatch(applyFilter(_filter));
};

export const clearSearch = () => (dispatch, getState) => {
  dispatch(edit(new Filter({ filters: [], sort: 'timestamp' })));
  return dispatch({
    type: CLEAR_SEARCH,
  });
}

export const addFilter = (filter) => (dispatch, getState) => {
  filter.value = checkFilterValue(filter.value);
  const instance = getState().getIn([ 'liveSearch', 'instance']);
  const filters = instance.get('filters');

  const index = getAppliedFilterIndex(filters, filter);
  if (index !== -1) {
    const oldFilter = filters.get(index);
    const updatedFilter = {
      ...oldFilter,
      value: oldFilter.value.concat(filter.value),
    };

    const updatedFilters = filters.set(index, updatedFilter);
    return dispatch(edit(instance.set('filters', updatedFilters)));
    // const index = instance.filters.findIndex(f => f.key === filter.key);
    // const oldFilter = instance.filters.get(index);
    // oldFilter.value = oldFilter.value.concat(filter.value);
    // return dispatch(edit(instance.setIn(['filters', index], oldFilter)));
  } else {
    const filters = instance.filters.push(filter);
    return dispatch(edit(instance.set('filters', filters)));
  }
}

export const addFilterByKeyAndValue = (key, value, operator = undefined) => (dispatch, getState) => {
  let defaultFilter = { ...liveFiltersMap[key] };
  defaultFilter.value = value;
  if (operator) {
    defaultFilter.operator = operator;
  }
  dispatch(addFilter(defaultFilter));
}

export const updateCurrentPage = reduceThenFetchResource((page, fromUrl=false) => ({
  type: UPDATE_CURRENT_PAGE,
  page,
}));

export function fetchFilterSearch(params) {
  params.live = true
  return {
    types: FETCH_FILTER_SEARCH.array,
    call: client => client.get('/events/search', params),
    params,
  };
}
