import { put, takeLatest, all, call, select } from 'redux-saga/effects';
import { config, zeus } from 'config/general';
import gql from 'graphql-tag';
import fetch from 'cross-fetch';

// Apis from parent
import { api } from 'store/apis';
// Action type
import { apolloCall } from 'store/utils/sagas';
// import  createHttpLink, InMemoryCache } from '@apollo/client';

import actions from './actions';
import selectors from './selectors';
import { messageModel, roomListModel, roomModel } from './models';

const { Zeus, $ } = zeus;

// const cache = new InMemoryCache();

// const client = new ApolloClient({
//   link: createHttpLink({
//     uri: config.api.messagerieUrlApollo || config.api.baseUrlApollo || '',
//     fetch,
//   }),
//   cache,
// });

/**
 * create conversation
 */
function* createRoom(action: storeAction): void {
  const payload = action && action.payload;

  const accountIds = payload.accountIds;

  let zeusMutation;
  try {
    zeusMutation = Zeus.mutation({
      roomsCreateOne: [
        {
          input: $`data`,
        },
        roomListModel,
      ],
    });
  } catch (error) {
    console.log('error detail', error);
    return;
  }

  const mutate = gql`
    ${zeusMutation}
  `;

  yield call(apolloCall, {
    mutate,
    objectReturn: 'roomsCreateOne',
    actionRes: actions.createRoom.result.action,
    success: payload.success,
    callback: payload.callback,
    data: { data: { accountIds } },
  });
}

/**
 * send message to conversation
 */
function* addMessageToRoom(action: storeAction): void {
  const payload = action && action.payload;

  let zeusMutation;
  try {
    zeusMutation = Zeus.mutation({
      roomsAddOneMessage: [
        {
          input: $`data`,
        },
        messageModel,
      ],
    });
  } catch (error) {
    console.log('error detail', error);
    return;
  }

  const mutate = gql`
    ${zeusMutation}
  `;

  yield call(apolloCall, {
    mutate,
    objectReturn: 'roomsAddOneMessage',
    actionRes: actions.addMessageToRoom.result.action,
    success: payload.success,
    callback: payload.callback,
    data: { data: payload.data },
    noLoading: true,
  });
}

/**
 * get a room
 */
function* getOneRoom(action: storeAction): void {
  const payload = action && action.payload;

  let zeusQuery;
  try {
    zeusQuery = Zeus.query({
      roomsGetOne: [
        {
          id: $`id`,
        },
        roomModel,
      ],
    });
  } catch (error) {
    console.log('error detail', error);
    return;
  }

  const query = gql`
    ${zeusQuery}
  `;

  yield call(apolloCall, {
    query,
    objectReturn: 'roomsGetOne',
    actionRes: actions.getOneRoom.result.action,
    success: payload.success,
    callback: payload.callback,
    data: { id: payload.id, pagination: payload.pagination },
  });
}

/**
 * get room messages
 */
function* getRoomMessages(action: storeAction): void {
  const payload = action && action.payload;
  const skip = yield select(selectors.getNumberMessages);

  let zeusQuery;
  try {
    zeusQuery = Zeus.query({
      roomsGetMessages: [
        {
          id: $`id`,
          pagination: $`pagination`,
        },
        messageModel,
      ],
    });
  } catch (error) {
    console.log('error detail', error);
    return;
  }

  const query = gql`
    ${zeusQuery}
  `;

  yield call(apolloCall, {
    query,
    objectReturn: 'roomsGetMessages',
    actionRes: actions.getRoomMessages.result.action,
    success: payload.success,
    callback: payload.callback,
    data: { id: payload.id, pagination: { skip: 0, limit: 20, sort: 'createdAt desc' } },
    noLoading: true,
  });
}

/**
 * get all rooms
 */
function* getRoomsList(action: storeAction): void {
  const payload = action && action.payload;

  let zeusQuery;
  try {
    zeusQuery = Zeus.query({
      roomsGetMany: [{}, roomModel],
    });
  } catch (error) {
    console.log('error detail', error);
    return;
  }

  const query = gql`
    ${zeusQuery}
  `;

  yield call(apolloCall, {
    query,
    objectReturn: 'roomsGetMany',
    actionRes: actions.getRoomsList.result.action,
    callback: payload && payload.callback,
  });
}

/**
 * mark messages as read
 */
function* markMessagesAsRead(action: storeAction): void {
  const payload = action && action.payload;

  let zeusMutation;
  try {
    zeusMutation = Zeus.mutation({
      roomsMarkAllMessageAsRead: [
        {
          roomId: $`roomId`,
        },
        roomListModel,
      ],
    });
  } catch (error) {
    console.log('error detail', error);
    return;
  }

  const mutate = gql`
    ${zeusMutation}
  `;

  yield call(apolloCall, {
    mutate,
    objectReturn: 'roomsMarkAllMessageAsRead',
    actionRes: actions.markMessagesAsRead.result.action,
    success: payload.success,
    callback: payload.callback,
    data: { roomId: payload.roomId },
    noLoading: true,
  });
}

function* messagerieWatchers() {
  yield all([
    yield takeLatest(actions.createRoom.request.constant, createRoom),
    yield takeLatest(actions.addMessageToRoom.request.constant, addMessageToRoom),
    yield takeLatest(actions.getOneRoom.request.constant, getOneRoom),
    yield takeLatest(actions.getRoomsList.request.constant, getRoomsList),
    yield takeLatest(actions.markMessagesAsRead.request.constant, markMessagesAsRead),
    yield takeLatest(actions.getRoomMessages.request.constant, getRoomMessages),
  ]);
}

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