import { put, takeEvery, all, call } from 'redux-saga/effects';

import gql from 'graphql-tag';

// Action type
import { StoreAction } from 'store/utils/actions';

import { genericApolloSaga } from 'store/utils/apollo';

import { config, zeus } from 'config/general';

import { clone, deepOmit } from 'store/utils/helper';
import actions from './actions';
import selectors from './selectors';
import * as models from './models';

const { Zeus, $ } = zeus;

export const treatmentOut = values => {
  const output = {
    ...values,
  };

  return deepOmit(output, ['_id', '__typename', 'createdAt', 'updatedAt']);
};

function* list(action: StoreAction) {
  action.payload = action.payload || {};
  const payload = action.payload;

  const search = payload.data || {};

  const zeusQuery = Zeus.query({
    myOrdersGetMany: [search, models.orderListModel],
  });

  payload.query = gql`
    ${zeusQuery}
  `;

  yield call(genericApolloSaga('ordersSearchMany', actions.list.result.action), action);
}

function* detail(action) {
  action.payload = action.payload || {};
  const payload = action.payload;

  const search = { id: payload.id };

  const zeusQuery = Zeus.query({
    myOrdersGetOne: [search, models.orderModel],
  });

  payload.query = gql`
    ${zeusQuery}
  `;

  yield call(genericApolloSaga('myOrdersGetOne', actions.detail.result.action), action);
}

function* current(action) {
  action.payload = action.payload || {};
  const payload = action.payload;

  const search = {};

  const zeusQuery = Zeus.query({
    myCurrentOrder: [search, models.orderModel],
  });

  payload.query = gql`
    ${zeusQuery}
  `;

  yield call(genericApolloSaga('myCurrentOrder', actions.current.result.action), action);
}

/**
 * MUTATIONS
 */

function* reserveOneBooking(action: StoreAction) {
  action.payload = action.payload || {};
  const payload = action.payload;

  const zeusMutation = Zeus.mutation({
    reserveOneBooking: [
      {
        input: $`input`,
      },
      models.orderModel,
    ],
  });

  payload.mutation = gql`
    ${zeusMutation}
  `;

  payload.data = {
    input: payload.data && treatmentOut(payload.data.input),
  };

  yield call(genericApolloSaga('reserveOneBooking', actions.add.result.action), action);
}

function* finaliseCheckoutWithStripe(action: StoreAction) {
  action.payload = action.payload || {};
  const payload = action.payload;

  const zeusMutation = Zeus.mutation({
    finaliseCheckoutWithStripe: [
      {
        input: $`input`,
      },
      models.orderModel,
    ],
  });

  payload.mutation = gql`
    ${zeusMutation}
  `;

  payload.data = {
    input: treatmentOut(payload.data),
  };

  yield call(
    genericApolloSaga(
      'finaliseCheckoutWithStripe',
      actions.finaliseCheckoutWithStripe.result.action,
    ),
    action,
  );
}

function* update(action: StoreAction) {
  action.payload = action.payload || {};
  const payload = action.payload;

  const zeusMutation = Zeus.mutation({
    myOrdersEditOne: [
      {
        id: payload.id,
        input: $`input`,
      },
      models.orderModel,
    ],
  });

  payload.mutation = gql`
    ${zeusMutation}
  `;

  payload.data = {
    input: payload.data && treatmentOut(payload.data.input),
  };

  yield call(genericApolloSaga('myOrdersEditOne', actions.update.result.action), action);
}

function* deleteOrder(action: StoreAction) {
  action.payload = action.payload || {};
  const payload = action.payload;

  const zeusMutation = Zeus.mutation({
    removeCurrentOrder: [{}, models.orderModel],
  });

  payload.mutation = gql`
    ${zeusMutation}
  `;

  yield call(genericApolloSaga('myOrdersDeleteOne', actions.delete.result.action), action);
}

function* orderWatchers() {
  yield all([
    takeEvery(actions.list.request.constant, list),
    takeEvery(actions.detail.request.constant, detail),
    takeEvery(actions.current.request.constant, current),
    takeEvery(actions.add.request.constant, reserveOneBooking),
    takeEvery(actions.finaliseCheckoutWithStripe.request.constant, finaliseCheckoutWithStripe),
    takeEvery(actions.update.request.constant, update),
    takeEvery(actions.update.request.constant, update),
    takeEvery(actions.delete.request.constant, deleteOrder),
  ]);
}

export default function* saga() {
  yield call(orderWatchers);
}
