import {
	select, put, call, take, takeLatest
} from 'redux-saga/effects';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';

import { CREATE_CHANNEL, LOGIN } from '../actions/actionsTypes';
import { createChannelSuccess, createChannelFailure } from '../actions/createChannel';
import { showErrorAlert } from '../utils/info';
import RocketChat from '../lib/rocketchat';
import Navigation from '../lib/Navigation';
import database from '../lib/database';
import I18n from '../i18n';
import { logEvent, events } from '../utils/log';
import { goRoom } from '../utils/goRoom';

const createChannel = function createChannel(data) {
	return RocketChat.createChannel(data);
};

const createGroupChat = function createGroupChat() {
	return RocketChat.createGroupChat();
};

const createTeam = function createTeam(data) {
	return RocketChat.createTeam(data);
};

const handleRequest = function* handleRequest({ data }) {
	try {
		const auth = yield select(state => state.login.isAuthenticated);
		if (!auth) {
			yield take(LOGIN.SUCCESS);
		}

		let sub;
		if (data.isTeam) {
			const {
				type,
				readOnly,
				broadcast,
				encrypted
			} = data;
			logEvent(events.CT_CREATE, {
				type,
				readOnly,
				broadcast,
				encrypted
			});
			const result = yield call(createTeam, data);
			sub = {
				rid: result?.team?.roomId,
				...result.team,
				t: result.team.type ? 'p' : 'c'
			};
		} else if (data.group) {
			logEvent(events.SELECTED_USERS_CREATE_GROUP);
			const result = yield call(createGroupChat);
			if (result.success) {
				sub = {
					rid: result.room?._id,
					...result.room
				};
			}
		} else {
			const {
				type,
				readOnly,
				broadcast,
				encrypted
			} = data;
			logEvent(events.CR_CREATE, {
				type: type ? 'private' : 'public',
				readOnly,
				broadcast,
				encrypted
			});
			const result = yield call(createChannel, data);
			sub = {
				rid: result?.channel?._id || result?.group?._id,
				...result?.channel,
				...result?.group
			};
		}
		try {
			const db = database.active;
			const subCollection = db.get('subscriptions');
			yield db.action(async() => {
				await subCollection.create((s) => {
					s._raw = sanitizedRaw({ id: sub.rid }, subCollection.schema);
					Object.assign(s, sub);
				});
			});
		} catch {
			// do nothing
		}
		yield put(createChannelSuccess(sub));
	} catch (err) {
		logEvent(events[data.group ? 'SELECTED_USERS_CREATE_GROUP_F' : 'CR_CREATE_F']);
		yield put(createChannelFailure(err, data.isTeam));
	}
};

const handleSuccess = function* handleSuccess({ data }) {
	const isMasterDetail = yield select(state => state.app.isMasterDetail);
	if (isMasterDetail) {
		Navigation.navigate('DrawerNavigator');
	}
	goRoom({ item: data, isMasterDetail });
};

const handleFailure = function handleFailure({ err, isTeam }) {
	setTimeout(() => {
		const msg = err.data.errorType ? I18n.t(err.data.errorType, { room_name: err.data.details.channel_name }) : err.reason || I18n.t('There_was_an_error_while_action', { action: isTeam ? I18n.t('creating_team') : I18n.t('creating_channel') });
		showErrorAlert(msg, isTeam ? I18n.t('Create_Team') : I18n.t('Create_Channel'));
	}, 300);
};

const root = function* root() {
	yield takeLatest(CREATE_CHANNEL.REQUEST, handleRequest);
	yield takeLatest(CREATE_CHANNEL.SUCCESS, handleSuccess);
	yield takeLatest(CREATE_CHANNEL.FAILURE, handleFailure);
};

export default root;