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

import gql from 'graphql-tag';

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

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

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

import { clone, convertObjectToArray, deepOmit } from 'store/utils/helper';
import geoloc from 'store/geoloc';
import { genericCall } from 'store/utils/sagas';
import { StoreState } from 'store/rootReducer';
import actions from './actions';
import selectors from './selectors';
import * as models from './models';

const { Zeus, $ } = zeus;

const treatmentImage = image => {
  const output = {
    ...image,
  };

  // output.fileType = undefined;
  // output.title = undefined;

  return output;
};

export const treatmentOut = values => {
  const output = {
    ...values,
  };
  if (output.features) {
    output.featureIds = convertObjectToArray(output.features);
    output.features = undefined;
  }
  if (output.equipments) {
    output.equipmentIds = convertObjectToArray(output.equipments);
    output.equipments = undefined;
  }

  if (output.maxCapacity) output.maxCapacity = parseInt(output.maxCapacity, 10);
  if (output.minStay) output.minStay = parseInt(output.minStay, 10);
  if (output.maxStay) output.maxStay = parseInt(output.maxStay, 10);

  if (output.pricingPerHour) output.pricingPerHour = parseInt(output.pricingPerHour, 10);
  if (output.finalPrice) output.finalPrice = parseFloat(output.finalPrice);

  if (output.cover) output.cover = treatmentImage(output.cover);

  if (output.extraImages) {
    for (let i = 0; i < output.extraImages.length; i++) {
      if (output.extraImages[i]) output.extraImages[i] = treatmentImage(output.extraImages[i]);
    }
  }

  // availability
  if (output.availability) {
    if (output.availability.exceptions) {
      for (let i = 0; i < output.availability.exceptions.length; i += 1) {
        const item = output.availability.exceptions[i];

        if (item.allDay) item.hours = undefined;
        else item.allDay = false;
      }
    }
  }

  return deepOmit(output, [
    '_id',
    '__typename',
    'createdAt',
    'createdBy',
    'updatedAt',
    'finalPrice',
    'place',
    'organisationId',
    'get.*',
  ]);
};

export const treatmentSearch = (params, geolocation: GeolocationPosition, limit = 10) => {
  const newParams = (params && clone(params)) || {};

  // written search has priority
  if (newParams.location) {
    newParams.geoSearchWithAddress = {
      formattedAddress: newParams.location,
      radius: 150000,
    };
    delete newParams.location;
  } else if (geolocation?.coords) {
    newParams.geoSearch = {
      latitude: geolocation.coords?.latitude,
      longitude: geolocation.coords?.longitude,
      radius: 150000,
    };
  }

  // types
  if (newParams.individual === 'true') {
    newParams.workspaceTypes = newParams.workspaceTypes || [];
    newParams.workspaceTypes.push('individual');
  }
  if (newParams.open === 'true') {
    newParams.workspaceTypes = newParams.workspaceTypes || [];
    newParams.workspaceTypes.push('open');
  }
  if (newParams.meeting === 'true') {
    newParams.workspaceTypes = newParams.workspaceTypes || [];
    newParams.workspaceTypes.push('meeting');
  }
  delete newParams.individual;
  delete newParams.open;
  delete newParams.meeting;

  if (newParams.people) {
    newParams.maxCapacity = params.people;
    newParams.people = undefined;
  }

  if (newParams.page && limit) {
    newParams.pagination = {
      limit,
      skip: (newParams.page - 1) * limit,
    };
    delete newParams.page;
  }

  return newParams;
};

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

  const geoSelection = yield select((state: StoreState) => state.geoloc?.geoloc?.data);

  const search = payload.data || {};

  const apiCalls = [];

  const location = search?.geoSearchWithAddress?.formattedAddress;

  if (location && (!geoSelection || geoSelection.formattedAddress !== location)) {
    apiCalls.push(
      call(genericCall, geoloc.actions.getGeocodeAddress, {
        data: {
          address: location,
        },
        noLoading: true,
      }),
    );
  }

  console.log('workspace search', search);

  const zeusQuery = Zeus.query({
    workspacesSearchMany: [search, models.workspaceListModel],
    workspacesGetCount: [search],
  });

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

  payload.name = 'workspacesSearchMany';

  console.log('action', action?.payload);
  apiCalls.push(call(genericApolloSaga('', actions.list.result.action), action));

  yield all(apiCalls);
}

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

  const search = { id: payload.id };

  const zeusQuery = Zeus.query({
    workspacesGetOne: [
      search,
      {
        ...models.workspaceModel,
        getBookings: [
          {},
          {
            ownerId: true,
            status: true,
            slot: {
              startDate: true,
              endDate: true,
              startTime: true,
              endTime: true,
            },
            dates: {
              startDate: true,
              endDate: true,
            },
          },
        ],
      },
    ],
  });

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

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

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

  const search = payload.data || {};

  if (payload.limit) {
    search.pagination = {
      limit: payload.limit,
      skip: ((payload.page || 1) - 1) * payload.limit,
    };
  }

  const zeusQuery = Zeus.query({
    workspacesGetMine: [search, models.workspaceListModel],
    workspacesGetMineCount: [search],
  });

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

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

/**
 * MUTATIONS
 */

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

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

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

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

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

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

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

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

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

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

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

  const zeusMutation = Zeus.mutation({
    workspacesDeleteOne: [
      {
        id: payload.id,
      },
      models.workspaceModel,
    ],
  });

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

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

function* workspaceWatchers() {
  yield all([
    takeEvery(actions.list.request.constant, list),
    takeEvery(actions.detail.request.constant, detail),
    takeEvery(actions.add.request.constant, add),
    takeEvery(actions.update.request.constant, update),
    takeEvery(actions.delete.request.constant, deleteWorkspace),
    takeEvery(actions.mine.request.constant, mine),
  ]);
}

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