import { takeEvery, all, call, put } from 'redux-saga/effects';
import { transRoutesSlice } from './../store';
import { TransRoutesService } from './../services';
import moment from 'moment';

const {
  fetchAllRoutes,
  fetchAllRoutesSuccess,
  fetchAllRoutesFailure,
  updateRoute,
  updateRouteFailure,
  fetchAllTomorrowRoutes,
  fetchAllTomorrowRoutesSuccess,
  fetchAllTomorrowRoutesFailure,
  createRoute,
  createRouteFailure,
  fetchAllHisotryRoutesSuccess,
  fetchAllHistoryRoutes,
  fetchAllHistoryRoutesFailure,
  fetchAllBreakfastRecords,
  fetchAllBreakfastRecordsSuccess,
  fetchAllBreakfastRecordsFailure,
  fetchAllLunchRecords,
  fetchAllLunchRecordsSuccess,
  fetchAllLunchRecordsFailure,
  fetchAllSnackRecords,
  fetchAllSnackRecordsSuccess,
  fetchAllSnackRecordsFailure
} = transRoutesSlice.actions;

function* fetchHistoryRoutesSaga(action) {
  try {
    const dateText = action.payload.dateText;
    const routes = (yield call(TransRoutesService.getAll, dateText)).data;
    yield put(fetchAllHisotryRoutesSuccess(routes));
  } catch(ex) {
    yield put(fetchAllHistoryRoutesFailure(ex));
  }
}

function* fetchRoutesSaga() {
  try {
    const date = new Date();
    const dateText = ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear();
    const routes = (yield call(TransRoutesService.getAll, dateText)).data;
    yield put(fetchAllRoutesSuccess(routes));
  } catch(ex) {
    yield put(fetchAllRoutesFailure(ex));
  }
}

function* fetchBreakfastsRecordsSaga() {
  try {
    const breakfasts = (yield call(TransRoutesService.getAllBreakfastRecords, moment(new Date()).format('MM/DD/YYYY')))?.data;
    yield put(fetchAllBreakfastRecordsSuccess(breakfasts));
  } catch(ex) {
    yield put(fetchAllBreakfastRecordsFailure(ex));
  }
}

function* fetchLunchRecordsSaga() {
  try {
    const lunches = (yield call(TransRoutesService.getAllLunchRecords, moment(new Date()).format('MM/DD/YYYY')))?.data;
    yield put(fetchAllLunchRecordsSuccess(lunches));
  } catch(ex) {
    yield put(fetchAllLunchRecordsFailure(ex));
  }
}

function* fetchSnackRecordsSaga() {
  try {
    const snacks = (yield call(TransRoutesService.getAllSnackRecords, moment(new Date()).format('MM/DD/YYYY')))?.data;
    yield put(fetchAllSnackRecordsSuccess(snacks));
  } catch(ex) {
    yield put(fetchAllSnackRecordsFailure(ex));
  }
}

// Tomorrow Doesn't really mean 'tomorrow' but maybe the selected future date.
function* fetchAllTomorrowRoutesSaga(action) {
  try {
    const date = new Date();
    date.setDate(date.getDate() + 1);
    const dateText = action.payload.dateText ? action.payload.dateText : ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear();
    const routes = (yield call(TransRoutesService.getAll, dateText)).data;
    yield put(fetchAllTomorrowRoutesSuccess(routes));
  } catch(ex) {
    yield put(fetchAllTomorrowRoutesFailure(ex));
  }
}

function* updateRouteSaga(action) {
  try {
    yield call(TransRoutesService.updateRoute, action.payload.id, action.payload.data);
    // yield call(TransRoutesService.updateInProgress, action.payload.data);
    if (action.payload.dateText) {
      const routes = (yield call(TransRoutesService.getAll, action.payload.dateText)).data;
      if (action.payload.fromSchedule) {
        yield put(fetchAllTomorrowRoutesSuccess(routes));
      } else {
        yield put(fetchAllHisotryRoutesSuccess(routes));
      }
      
    } else if (!action.payload.skipRefetch) {
      // Only refetch today's routes by default (not tomorrow's too)
      const date = new Date();
      const dateText = ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear();
      const routes = (yield call(TransRoutesService.getAll, dateText)).data;
      yield put(fetchAllRoutesSuccess(routes));
    }
    if (action.payload.callback) {
      action.payload.callback();
    }
  } catch(ex) {
    yield put(updateRouteFailure(ex));
    window.alert(`Fail to Update Route: ${typeof ex === 'string' ? ex : JSON.stringify(ex)}` )
  }
}

function* createRouteSaga(action) {
  try {
    yield call(TransRoutesService.createNewRoute, action.payload.data);
    if (action.payload.fetchToday) {
      const date = new Date();
      const dateText = ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear();
      const routes = (yield call(TransRoutesService.getAll, dateText)).data;
      yield put(fetchAllRoutesSuccess(routes));
    }
    if (action.payload.fetchTomorrow) {
      const date = new Date();
      date.setDate(date.getDate() + 1);
      const dateText = ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear();
      const routes = (yield call(TransRoutesService.getAll, dateText)).data;
      yield put(fetchAllTomorrowRoutesSuccess(routes));
    }
    if (action.payload.fetchDate) {
      const routes = (yield call(TransRoutesService.getAll, action.payload.fetchDate)).data;
      yield put(fetchAllTomorrowRoutesSuccess(routes));
    }
  } catch(ex) {
    yield put(createRouteFailure(ex));
    window.alert(`Fail to Create Route: ${typeof ex === 'string' ? ex : JSON.stringify(ex)}` )
  }
}

export function* transRoutesEffect() {
  yield all([
    yield takeEvery(fetchAllRoutes.type, fetchRoutesSaga),
    yield takeEvery(updateRoute.type, updateRouteSaga),
    yield takeEvery(fetchAllTomorrowRoutes.type, fetchAllTomorrowRoutesSaga),
    yield takeEvery(createRoute.type, createRouteSaga),
    yield takeEvery(fetchAllHistoryRoutes.type, fetchHistoryRoutesSaga),
    yield takeEvery(fetchAllBreakfastRecords.type, fetchBreakfastsRecordsSaga),
    yield takeEvery(fetchAllLunchRecords.type, fetchLunchRecordsSaga),
    yield takeEvery(fetchAllSnackRecords.type, fetchSnackRecordsSaga)
  ])
};